Add a C++ interface to the optimization functionalities.
diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt
index aa85eb2..2fab5fc 100644
--- a/source/opt/CMakeLists.txt
+++ b/source/opt/CMakeLists.txt
@@ -27,6 +27,7 @@
   module.h
   null_pass.h
   reflect.h
+  optimizer.hpp
   pass.h
   passes.h
   pass_manager.h
@@ -47,6 +48,7 @@
   libspirv.cpp
   module.cpp
   set_spec_constant_default_value_pass.cpp
+  optimizer.cpp
   pass_manager.cpp
   strip_debug_info_pass.cpp
   types.cpp
diff --git a/source/opt/eliminate_dead_constant_pass.h b/source/opt/eliminate_dead_constant_pass.h
index 6e9a278..6107cad 100644
--- a/source/opt/eliminate_dead_constant_pass.h
+++ b/source/opt/eliminate_dead_constant_pass.h
@@ -21,11 +21,7 @@
 namespace spvtools {
 namespace opt {
 
-// The optimization pass to remove dead constants, including front-end
-// contants: defined by OpConstant, OpConstantComposite, OpConstantTrue and
-// OpConstantFalse; and spec constants: defined by OpSpecConstant,
-// OpSpecConstantComposite, OpSpecConstantTrue, OpSpecConstantFalse and
-// OpSpecConstantOp.
+// See optimizer.hpp for documentation.
 class EliminateDeadConstantPass : public Pass {
  public:
   const char* name() const override { return "eliminate-dead-const"; }
diff --git a/source/opt/fold_spec_constant_op_and_composite_pass.h b/source/opt/fold_spec_constant_op_and_composite_pass.h
index 7b07fbf..8bca3e5 100644
--- a/source/opt/fold_spec_constant_op_and_composite_pass.h
+++ b/source/opt/fold_spec_constant_op_and_composite_pass.h
@@ -29,25 +29,7 @@
 namespace spvtools {
 namespace opt {
 
-// The optimization pass that folds "Spec Constants", which are defined by
-// OpSpecConstantOp and OpSpecConstantComposite instruction, to "Normal
-// Constants", which are defined by OpConstantTrue, OpConstantFalse,
-// OpConstant, OpConstantNull and OpConstantComposite instructions. Note that
-// Spec Constants defined with OpSpecConstant, OpSpecConstantTrue and
-// OpSpecConstantFalse instructions are not handled, as these instructions
-// indicate their value are not determined and can be changed in future.  A
-// Spec Constant is foldable if all of its value(s) can be determined from the
-// module. For example, an Integer Spec Constant defined with OpSpecConstantOp
-// instruction can be folded if its value won't change later. This pass will
-// replace the original OpSpecContantOp instruction with an OpConstant
-// instruction. When folding composite type Spec Constants, new instructions
-// may be inserted to define the components of the composite constant first,
-// then the original Spec Constants will be replace with OpConstantComposite
-// instructions.
-// There are some operations not supported:
-//  OpSConvert, OpFConvert, OpQuantizeToF16 and all the operations under Kernel
-//  capability.
-// TODO(qining): Add support for the operations listed above.
+// See optimizer.hpp for documentation.
 class FoldSpecConstantOpAndCompositePass : public Pass {
  public:
   FoldSpecConstantOpAndCompositePass();
diff --git a/source/opt/freeze_spec_constant_value_pass.h b/source/opt/freeze_spec_constant_value_pass.h
index 5e74a42..a04ff03 100644
--- a/source/opt/freeze_spec_constant_value_pass.h
+++ b/source/opt/freeze_spec_constant_value_pass.h
@@ -21,14 +21,7 @@
 namespace spvtools {
 namespace opt {
 
-// The transformation pass that specializes the value of spec constants to
-// their default values. This pass only processes the spec constants that have
-// Spec ID decorations (defined by OpSpecConstant, OpSpecConstantTrue and
-// OpSpecConstantFalse instructions) and replaces them with their front-end
-// version counterparts (OpConstant, OpConstantTrue and OpConstantFalse). The
-// corresponding Spec ID annotation instructions will also be removed. This
-// pass does not fold the newly added front-end constants and does not process
-// other spec constants defined by OpSpecConstantComposite or OpSpecConstantOp.
+// See optimizer.hpp for documentation.
 class FreezeSpecConstantValuePass : public Pass {
  public:
   const char* name() const override { return "freeze-spec-const"; }
diff --git a/source/opt/null_pass.h b/source/opt/null_pass.h
index a3306b5..832e891 100644
--- a/source/opt/null_pass.h
+++ b/source/opt/null_pass.h
@@ -21,7 +21,7 @@
 namespace spvtools {
 namespace opt {
 
-// A null pass that does nothing.
+// See optimizer.hpp for documentation.
 class NullPass : public Pass {
  public:
   const char* name() const override { return "null"; }
diff --git a/source/opt/optimizer.cpp b/source/opt/optimizer.cpp
new file mode 100644
index 0000000..da337db
--- /dev/null
+++ b/source/opt/optimizer.cpp
@@ -0,0 +1,121 @@
+// Copyright (c) 2016 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.
+
+#include "optimizer.hpp"
+
+#include "build_module.h"
+#include "make_unique.h"
+#include "pass_manager.h"
+#include "passes.h"
+
+namespace spvtools {
+
+struct Optimizer::PassToken::Impl {
+  Impl(std::unique_ptr<opt::Pass> p) : pass(std::move(p)) {}
+
+  std::unique_ptr<opt::Pass> pass;  // Internal implementation pass.
+};
+
+Optimizer::PassToken::PassToken(
+    std::unique_ptr<Optimizer::PassToken::Impl> impl)
+    : impl_(std::move(impl)) {}
+Optimizer::PassToken::PassToken(PassToken&& that)
+    : impl_(std::move(that.impl_)) {}
+
+Optimizer::PassToken& Optimizer::PassToken::operator=(PassToken&& that) {
+  impl_ = std::move(that.impl_);
+  return *this;
+}
+
+Optimizer::PassToken::~PassToken() {}
+
+struct Optimizer::Impl {
+  explicit Impl(spv_target_env env) : target_env(env), pass_manager() {}
+
+  const spv_target_env target_env;  // Target environment.
+  opt::PassManager pass_manager;    // Internal implementation pass manager.
+};
+
+Optimizer::Optimizer(spv_target_env env) : impl_(new Impl(env)) {}
+
+Optimizer::~Optimizer() {}
+
+void Optimizer::SetMessageConsumer(MessageConsumer c) {
+  // All passes' message consumer needs to be updated.
+  for (uint32_t i = 0; i < impl_->pass_manager.NumPasses(); ++i) {
+    impl_->pass_manager.GetPass(i)->SetMessageConsumer(c);
+  }
+  impl_->pass_manager.SetMessageConsumer(std::move(c));
+}
+
+Optimizer& Optimizer::RegisterPass(PassToken&& p) {
+  // Change to use the pass manager's consumer.
+  p.impl_->pass->SetMessageConsumer(impl_->pass_manager.consumer());
+  impl_->pass_manager.AddPass(std::move(p.impl_->pass));
+  return *this;
+}
+
+bool Optimizer::Run(const uint32_t* original_binary,
+                    const size_t original_binary_size,
+                    std::vector<uint32_t>* optimized_binary) const {
+  std::unique_ptr<ir::Module> module =
+      BuildModule(impl_->target_env, impl_->pass_manager.consumer(),
+                  original_binary, original_binary_size);
+  if (module == nullptr) return false;
+
+  auto status = impl_->pass_manager.Run(module.get());
+  if (status == opt::Pass::Status::SuccessWithChange) {
+    optimized_binary->clear();
+    module->ToBinary(optimized_binary, /* skip_nop = */ true);
+  }
+
+  return status != opt::Pass::Status::Failure;
+}
+
+Optimizer::PassToken CreateNullPass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
+}
+
+Optimizer::PassToken CreateStripDebugInfoPass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::StripDebugInfoPass>());
+}
+
+Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
+    const std::unordered_map<uint32_t, std::string>& id_value_map) {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::SetSpecConstantDefaultValuePass>(id_value_map));
+}
+
+Optimizer::PassToken CreateFreezeSpecConstantValuePass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::FreezeSpecConstantValuePass>());
+}
+
+Optimizer::PassToken CreateFoldSpecConstantOpAndCompositePass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::FoldSpecConstantOpAndCompositePass>());
+}
+
+Optimizer::PassToken CreateUnifyConstantPass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::UnifyConstantPass>());
+}
+
+Optimizer::PassToken CreateEliminateDeadConstantPass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::EliminateDeadConstantPass>());
+}
+
+}  // namespace spvtools
diff --git a/source/opt/optimizer.hpp b/source/opt/optimizer.hpp
new file mode 100644
index 0000000..8a84dfd
--- /dev/null
+++ b/source/opt/optimizer.hpp
@@ -0,0 +1,173 @@
+// Copyright (c) 2016 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.
+
+#ifndef SPIRV_TOOLS_OPTIMIZER_HPP_
+#define SPIRV_TOOLS_OPTIMIZER_HPP_
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "libspirv.hpp"
+#include "message.h"
+
+namespace spvtools {
+
+// C++ interface for SPIR-V optimization functionalities. It wraps the context
+// (including target environment and the corresponding SPIR-V grammar) and
+// provides methods for registering optimization passes and optimizing.
+//
+// Instances of this class provides basic thread-safety guarantee.
+class Optimizer {
+ public:
+  // The token for an optimization pass. It is returned via one of the
+  // Create*Pass() standalone functions at the end of this header file and
+  // consumed by the RegisterPass() method. Tokens are one-time objects that
+  // only support move; copying is not allowed.
+  struct PassToken {
+    struct Impl;  // Opaque struct for holding inernal data.
+
+    PassToken(std::unique_ptr<Impl>);
+
+    // Tokens can only be moved. Copying is disabled.
+    PassToken(const PassToken&) = delete;
+    PassToken(PassToken&&);
+    PassToken& operator=(const PassToken&) = delete;
+    PassToken& operator=(PassToken&&);
+
+    ~PassToken();
+
+    std::unique_ptr<Impl> impl_;  // Unique pointer to internal data.
+  };
+
+  // Constructs an instance with the given target |env|, which is used to decode
+  // the binaries to be optimized later.
+  //
+  // The constructed instance will have an empty message consumer, which just
+  // ignores all messages from the library. Use SetMessageConsumer() to supply
+  // one if messages are of concern.
+  explicit Optimizer(spv_target_env env);
+
+  // Disables copy/move constructor/assignment operations.
+  Optimizer(const Optimizer&) = delete;
+  Optimizer(Optimizer&&) = delete;
+  Optimizer& operator=(const Optimizer&) = delete;
+  Optimizer& operator=(Optimizer&&) = delete;
+
+  // Destructs this instance.
+  ~Optimizer();
+
+  // Sets the message consumer to the given |consumer|. The |consumer| will be
+  // invoked once for each message communicated from the library.
+  void SetMessageConsumer(MessageConsumer consumer);
+
+  // Registers the given |pass| to this optimizer. Passes will be run in the
+  // exact order of registration. The token passed in will be consumed by this
+  // method.
+  Optimizer& RegisterPass(PassToken&& pass);
+
+  // Optimizes the given SPIR-V module |original_binary| and writes the
+  // optimized binary into |optimized_binary|.
+  // Returns true on successful optimization, whether or not the module is
+  // modified. Returns false if errors occur when processing |original_binary|
+  // using any of the registered passes. In that case, no further passes are
+  // excuted and the contents in |optimized_binary| may be invalid.
+  //
+  // It's allowed to alias |original_binary| to the start of |optimized_binary|.
+  bool Run(const uint32_t* original_binary, size_t original_binary_size,
+           std::vector<uint32_t>* optimized_binary) const;
+
+ private:
+  struct Impl;                  // Opaque struct for holding internal data.
+  std::unique_ptr<Impl> impl_;  // Unique pointer to internal data.
+};
+
+// Creates a null pass.
+// A null pass does nothing to the SPIR-V module to be optimized.
+Optimizer::PassToken CreateNullPass();
+
+// Creates a strip-debug-info pass.
+// A strip-debug-info pass removes all debug instructions (as documented in
+// Section 3.32.2 of the SPIR-V spec) of the SPIR-V module to be optimized.
+Optimizer::PassToken CreateStripDebugInfoPass();
+
+// Creates a set-spec-constant-default-value pass.
+// A set-spec-constant-default-value pass sets the default values for the
+// spec constants that have SpecId decorations (i.e., those defined by
+// OpSpecConstant{|True|False} instructions).
+Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
+    const std::unordered_map<uint32_t, std::string>& id_value_map);
+
+// Creates a freeze-spec-constant-value pass.
+// A freeze-spec-constant pass specializes the value of spec constants to
+// their default values. This pass only processes the spec constants that have
+// SpecId decorations (defined by OpSpecConstant, OpSpecConstantTrue, or
+// OpSpecConstantFalse instructions) and replaces them with their normal
+// counterparts (OpConstant, OpConstantTrue, or OpConstantFalse). The
+// corresponding SpecId annotation instructions will also be removed. This
+// pass does not fold the newly added normal constants and does not process
+// other spec constants defined by OpSpecConstantComposite or
+// OpSpecConstantOp.
+Optimizer::PassToken CreateFreezeSpecConstantValuePass();
+
+// Creates a fold-spec-constant-op-and-composite pass.
+// A fold-spec-constant-op-and-composite pass folds spec constants defined by
+// OpSpecConstantOp or OpSpecConstantComposite instruction, to normal Constants
+// defined by OpConstantTrue, OpConstantFalse, OpConstant, OpConstantNull, or
+// OpConstantComposite instructions. Note that spec constants defined with
+// OpSpecConstant, OpSpecConstantTrue, or OpSpecConstantFalse instructions are
+// not handled, as these instructions indicate their value are not determined
+// and can be changed in future. A spec constant is foldable if all of its
+// value(s) can be determined from the module. E.g., an integer spec constant
+// defined with OpSpecConstantOp instruction can be folded if its value won't
+// change later. This pass will replace the original OpSpecContantOp instruction
+// with an OpConstant instruction. When folding composite spec constants,
+// new instructions may be inserted to define the components of the composite
+// constant first, then the original spec constants will be replaced by
+// OpConstantComposite instructions.
+//
+// There are some operations not supported yet:
+//   OpSConvert, OpFConvert, OpQuantizeToF16 and
+//   all the operations under Kernel capability.
+// TODO(qining): Add support for the operations listed above.
+Optimizer::PassToken CreateFoldSpecConstantOpAndCompositePass();
+
+// Creates a unify-constant pass.
+// A unify-constant pass de-duplicates the constants. Constants with the exact
+// same value and identical form will be unified and only one constant will
+// be kept for each unique pair of type and value.
+// There are several cases not handled by this pass:
+//  1) Constants defined by OpConstantNull instructions (null constants) and
+//  constants defined by OpConstantFalse, OpConstant or OpConstantComposite
+//  with value 0 (zero-valued normal constants) are not considered equivalent.
+//  So null constants won't be used to replace zero-valued normal constants,
+//  vice versa.
+//  2) Whenever there are decorations to the constant's result id id, the
+//  constant won't be handled, which means, it won't be used to replace any
+//  other constants, neither can other constants replace it.
+//  3) NaN in float point format with different bit patterns are not unified.
+Optimizer::PassToken CreateUnifyConstantPass();
+
+// Creates a eliminate-dead-constant pass.
+// A eliminate-dead-constant pass removes dead constants, including normal
+// contants defined by OpConstant, OpConstantComposite, OpConstantTrue, or
+// OpConstantFalse and spec constants defined by OpSpecConstant,
+// OpSpecConstantComposite, OpSpecConstantTrue, OpSpecConstantFalse or
+// OpSpecConstantOp.
+Optimizer::PassToken CreateEliminateDeadConstantPass();
+
+}  // namespace spvtools
+
+#endif  // SPIRV_TOOLS_OPTIMIZER_HPP_
diff --git a/source/opt/set_spec_constant_default_value_pass.h b/source/opt/set_spec_constant_default_value_pass.h
index 89e6b28..ad6b142 100644
--- a/source/opt/set_spec_constant_default_value_pass.h
+++ b/source/opt/set_spec_constant_default_value_pass.h
@@ -25,9 +25,7 @@
 namespace spvtools {
 namespace opt {
 
-// The optimization pass that sets the default values for the spec constants
-// that have SpecId decorations (i.e. those defined by
-// OpSpecConstant{|True|False} instructions).
+// See optimizer.hpp for documentation.
 class SetSpecConstantDefaultValuePass : public Pass {
  public:
   using SpecIdToValueStrMap = std::unordered_map<uint32_t, std::string>;
diff --git a/source/opt/strip_debug_info_pass.h b/source/opt/strip_debug_info_pass.h
index 0c3216d..626f9a8 100644
--- a/source/opt/strip_debug_info_pass.h
+++ b/source/opt/strip_debug_info_pass.h
@@ -21,8 +21,7 @@
 namespace spvtools {
 namespace opt {
 
-// The optimization pass for removing debug instructions (as documented in
-// Section 3.32.2 of the SPIR-V spec).
+// See optimizer.hpp for documentation.
 class StripDebugInfoPass : public Pass {
  public:
   const char* name() const override { return "strip-debug"; }
diff --git a/source/opt/unify_const_pass.h b/source/opt/unify_const_pass.h
index 1a45089..4fd8c64 100644
--- a/source/opt/unify_const_pass.h
+++ b/source/opt/unify_const_pass.h
@@ -21,19 +21,7 @@
 namespace spvtools {
 namespace opt {
 
-// The optimization pass to de-duplicate the constants. Constants with exactly
-// same values and identical form will be unified and only one constant will be
-// kept for each unique pair of type and value.
-// There are several cases not handled by this pass:
-//  1) Constants defined by OpConstantNull instructions (null constants) and
-//  constants defined by OpConstantFalse, OpConstant or OpConstantComposite
-//  with value(s) 0 (zero-valued normal constants) are not considered
-//  equivalent. So null constants won't be used to replace zero-valued normal
-//  constants, and other constants won't replace the null constants either.
-//  2) Whenever there are decorations to the constant's result id or its type
-//  id, the constants won't be handled, which means, it won't be used to
-//  replace any other constants, neither can other constants replace it.
-//  3) NaN in float point format with different bit patterns are not unified.
+// See optimizer.hpp for documentation.
 class UnifyConstantPass : public Pass {
  public:
   const char* name() const override { return "unify-const"; }
diff --git a/test/cpp_interface.cpp b/test/cpp_interface.cpp
index ce0d5be..c24c35a 100644
--- a/test/cpp_interface.cpp
+++ b/test/cpp_interface.cpp
@@ -15,7 +15,7 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include "opt/libspirv.hpp"
+#include "opt/optimizer.hpp"
 #include "spirv/1.1/spirv.h"
 
 namespace {
@@ -160,4 +160,104 @@
   EXPECT_EQ(1, invocation_count);
 }
 
+// Checks that after running the given optimizer |opt| on the given |original|
+// source code, we can get the given |optimized| source code.
+void CheckOptimization(const char* original, const char* optimized,
+                       const Optimizer& opt) {
+  SpvTools t(SPV_ENV_UNIVERSAL_1_1);
+  std::vector<uint32_t> original_binary;
+  ASSERT_TRUE(t.Assemble(original, &original_binary));
+
+  std::vector<uint32_t> optimized_binary;
+  EXPECT_TRUE(opt.Run(original_binary.data(), original_binary.size(),
+                      &optimized_binary));
+
+  std::string optimized_text;
+  EXPECT_TRUE(t.Disassemble(optimized_binary, &optimized_text));
+  EXPECT_EQ(optimized, optimized_text);
+}
+
+TEST(CppInterface, OptimizeEmptyModule) {
+  SpvTools t(SPV_ENV_UNIVERSAL_1_1);
+  std::vector<uint32_t> binary;
+  EXPECT_TRUE(t.Assemble("", &binary));
+
+  Optimizer o(SPV_ENV_UNIVERSAL_1_1);
+  o.RegisterPass(CreateStripDebugInfoPass());
+  EXPECT_TRUE(o.Run(binary.data(), binary.size(), &binary));
+}
+
+TEST(CppInterface, OptimizeModifiedModule) {
+  Optimizer o(SPV_ENV_UNIVERSAL_1_1);
+  o.RegisterPass(CreateStripDebugInfoPass());
+  CheckOptimization("OpSource GLSL 450", "", o);
+}
+
+TEST(CppInterface, OptimizeMulitplePasses) {
+  const char* original_text =
+      "OpSource GLSL 450 "
+      "OpDecorate %true SpecId 1 "
+      "%bool = OpTypeBool "
+      "%true = OpSpecConstantTrue %bool";
+
+  Optimizer o(SPV_ENV_UNIVERSAL_1_1);
+  o.RegisterPass(CreateStripDebugInfoPass())
+      .RegisterPass(CreateFreezeSpecConstantValuePass());
+
+  const char* expected_text =
+      "%bool = OpTypeBool\n"
+      "%1 = OpConstantTrue %bool\n";
+
+  CheckOptimization(original_text, expected_text, o);
+}
+
+TEST(CppInterface, OptimizeDoNothingWithPassToken) {
+  CreateFreezeSpecConstantValuePass();
+  auto token = CreateUnifyConstantPass();
+}
+
+TEST(CppInterface, OptimizeReassignPassToken) {
+  auto token = CreateNullPass();
+  token = CreateStripDebugInfoPass();
+
+  CheckOptimization(
+      "OpSource GLSL 450", "",
+      Optimizer(SPV_ENV_UNIVERSAL_1_1).RegisterPass(std::move(token)));
+}
+
+TEST(CppInterface, OptimizeMoveConstructPassToken) {
+  auto token1 = CreateStripDebugInfoPass();
+  Optimizer::PassToken token2(std::move(token1));
+
+  CheckOptimization(
+      "OpSource GLSL 450", "",
+      Optimizer(SPV_ENV_UNIVERSAL_1_1).RegisterPass(std::move(token2)));
+}
+
+TEST(CppInterface, OptimizeMoveAssignPassToken) {
+  auto token1 = CreateStripDebugInfoPass();
+  auto token2 = CreateNullPass();
+  token2 = std::move(token1);
+
+  CheckOptimization(
+      "OpSource GLSL 450", "",
+      Optimizer(SPV_ENV_UNIVERSAL_1_1).RegisterPass(std::move(token2)));
+}
+
+TEST(CppInterface, OptimizeSameAddressForOriginalOptimizedBinary) {
+  SpvTools t(SPV_ENV_UNIVERSAL_1_1);
+  std::vector<uint32_t> binary;
+  ASSERT_TRUE(t.Assemble("OpSource GLSL 450", &binary));
+
+  EXPECT_TRUE(Optimizer(SPV_ENV_UNIVERSAL_1_1)
+                  .RegisterPass(CreateStripDebugInfoPass())
+                  .Run(binary.data(), binary.size(), &binary));
+
+  std::string optimized_text;
+  EXPECT_TRUE(t.Disassemble(binary, &optimized_text));
+  EXPECT_EQ("", optimized_text);
+}
+
+// TODO(antiagainst): tests for SetMessageConsumer().
+
 }  // anonymous namespace