Merge pull request #5109 from haberman/integrate

Down-integrate from google3.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..49b1941
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,85 @@
+# Contributing to Protocol Buffers
+
+We welcome your contributions to protocol buffers. This doc describes the
+process to contribute patches to protobuf and the general guidelines we
+expect contributors to follow.
+
+## Before You Start
+
+We accept patches in the form of github pull requests. If you are new to
+github, please read [How to create github pull requests](https://help.github.com/articles/about-pull-requests/)
+first.
+
+### Contributor License Agreements
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution,
+this simply gives us permission to use and redistribute your contributions
+as part of the project.
+
+* 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](https://cla.developers.google.com/about/google-individual?csw=1).
+* If you work for a company that wants to allow you to contribute your work,
+  then you'll need to sign a [corporate CLA](https://cla.developers.google.com/about/google-corporate?csw=1).
+
+### Coding Style
+
+This project follows [Google’s Coding Style Guides](https://github.com/google/styleguide).
+Before sending out your pull request, please familiarize yourself with the
+corresponding style guides and make sure the proposed code change is style
+conforming.
+
+## Contributing Process
+
+Most pull requests should go to the master branch and the change will be
+included in the next major/minor version release (e.g., 3.6.0 release). If you
+need to include a bug fix in a patch release (e.g., 3.5.2), make sure it’s
+already merged to master, and then create a pull request cherry-picking the
+commits from master branch to the release branch (e.g., branch 3.5.x).
+
+For each pull request, a protobuf team member will be assigned to review the
+pull request. For minor cleanups, the pull request may be merged right away
+after an initial review. For larger changes, you will likely receive multiple
+rounds of comments and it may take some time to complete. We will try to keep
+our response time within 7-days but if you don’t get any response in a few
+days, feel free to comment on the threads to get our attention. We also expect
+you to respond to our comments within a reasonable amount of time. If we don’t
+hear from you for 2 weeks or longer, we may close the pull request. You can
+still send the pull request again once you have time to work on it.
+
+Once a pull request is merged, we will take care of the rest and get it into
+the final release.
+
+## Pull Request Guidelines
+
+* If you are a Googler, it is preferable to first create an internal CL and
+  have it reviewed and submitted. The code propagation process will deliver the
+  change to GitHub.
+* Create small PRs that are narrowly focused on addressing a single concern.
+  We often receive PRs that are trying to fix several things at a time, but if
+  only one fix is considered acceptable, nothing gets merged and both author's
+  & review's time is wasted. Create more PRs to address different concerns and
+  everyone will be happy.
+* For speculative changes, consider opening an issue and discussing it first.
+  If you are suggesting a behavioral or API change, make sure you get explicit
+  support from a protobuf team member before sending us the pull request.
+* Provide a good PR description as a record of what change is being made and
+  why it was made. Link to a GitHub issue if it exists.
+* Don't fix code style and formatting unless you are already changing that
+  line to address an issue. PRs with irrelevant changes won't be merged. If
+  you do want to fix formatting or style, do that in a separate PR.
+* Unless your PR is trivial, you should expect there will be reviewer comments
+  that you'll need to address before merging. We expect you to be reasonably
+  responsive to those comments, otherwise the PR will be closed after 2-3 weeks
+  of inactivity.
+* Maintain clean commit history and use meaningful commit messages. PRs with
+  messy commit history are difficult to review and won't be merged. Use rebase
+  -i upstream/master to curate your commit history and/or to bring in latest
+  changes from master (but avoid rebasing in the middle of a code review).
+* Keep your PR up to date with upstream/master (if there are merge conflicts,
+  we can't really merge your change).
+* All tests need to be passing before your change can be merged. We recommend
+  you run tests locally before creating your PR to catch breakages early on.
+  Ultimately, the green signal will be provided by our testing infrastructure.
+  The reviewer will help you if there are test failures that seem not related
+  to the change you are making.
diff --git a/Makefile.am b/Makefile.am
index 6694dff..b0913a5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1043,6 +1043,7 @@
   WORKSPACE                              \
   cmake/CMakeLists.txt                   \
   cmake/README.md                        \
+  cmake/conformance.cmake                   \
   cmake/examples.cmake                   \
   cmake/extract_includes.bat.in          \
   cmake/install.cmake                    \
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index ece39f7..06436c3 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -30,6 +30,7 @@
 
 # Options
 option(protobuf_BUILD_TESTS "Build tests" ON)
+option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF)
 option(protobuf_BUILD_EXAMPLES "Build examples" OFF)
 option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON)
 if (BUILD_SHARED_LIBS)
@@ -218,6 +219,10 @@
   include(tests.cmake)
 endif (protobuf_BUILD_TESTS)
 
+if (protobuf_BUILD_CONFORMANCE)
+  include(conformance.cmake)
+endif (protobuf_BUILD_CONFORMANCE)
+
 include(install.cmake)
 
 if (protobuf_BUILD_EXAMPLES)
diff --git a/cmake/conformance.cmake b/cmake/conformance.cmake
new file mode 100644
index 0000000..ec1f9e0
--- /dev/null
+++ b/cmake/conformance.cmake
@@ -0,0 +1,48 @@
+
+add_custom_command(
+  OUTPUT ${protobuf_source_dir}/conformance/conformance.pb.cc
+  DEPENDS protoc ${protobuf_source_dir}/conformance/conformance.proto
+  COMMAND protoc ${protobuf_source_dir}/conformance/conformance.proto
+      --proto_path=${protobuf_source_dir}/conformance
+      --cpp_out=${protobuf_source_dir}/conformance
+)
+
+add_custom_command(
+  OUTPUT ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.pb.cc
+         ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.pb.cc
+  DEPENDS protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
+          protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto
+  COMMAND protoc ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.proto
+                 ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.proto
+      --proto_path=${protobuf_source_dir}/src
+      --cpp_out=${protobuf_source_dir}/src
+)
+
+add_executable(conformance_test_runner
+  ${protobuf_source_dir}/conformance/conformance.pb.cc
+  ${protobuf_source_dir}/conformance/conformance_test.cc
+  ${protobuf_source_dir}/conformance/conformance_test_impl.cc
+  ${protobuf_source_dir}/conformance/conformance_test_runner.cc
+  ${protobuf_source_dir}/conformance/third_party/jsoncpp/json.h
+  ${protobuf_source_dir}/conformance/third_party/jsoncpp/jsoncpp.cpp
+  ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.pb.cc
+)
+
+add_executable(conformance_cpp
+  ${protobuf_source_dir}/conformance/conformance.pb.cc
+  ${protobuf_source_dir}/conformance/conformance_cpp.cc
+  ${protobuf_source_dir}/src/google/protobuf/test_messages_proto3.pb.cc
+  ${protobuf_source_dir}/src/google/protobuf/test_messages_proto2.pb.cc
+)
+
+target_include_directories(
+  conformance_test_runner
+  PUBLIC ${protobuf_source_dir}/conformance)
+
+target_include_directories(
+  conformance_cpp
+  PUBLIC ${protobuf_source_dir}/conformance)
+
+target_link_libraries(conformance_test_runner libprotobuf)
+target_link_libraries(conformance_cpp libprotobuf)
diff --git a/conformance/Makefile.am b/conformance/Makefile.am
index e51ab80..29d9a98 100644
--- a/conformance/Makefile.am
+++ b/conformance/Makefile.am
@@ -206,6 +206,7 @@
 
 conformance_test_runner_LDADD = $(top_srcdir)/src/libprotobuf.la
 conformance_test_runner_SOURCES = conformance_test.h conformance_test.cc \
+                                  conformance_test_impl.cc               \
                                   conformance_test_runner.cc             \
                                   third_party/jsoncpp/json.h             \
                                   third_party/jsoncpp/jsoncpp.cpp
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc
index 0a45f9b..2d822c2 100644
--- a/conformance/conformance_test.cc
+++ b/conformance/conformance_test.cc
@@ -57,34 +57,6 @@
 namespace google {
 namespace protobuf {
 
-std::set<ConformanceTestSuite*> *conformance_test_suite_set;
-GOOGLE_PROTOBUF_DECLARE_ONCE(conformance_test_suite_set_init_);
-
-void DeleteConformanceTestSuiteSet() {
-  delete conformance_test_suite_set;
-}
-
-static void InitConformanceTestSuiteSet() {
-  conformance_test_suite_set = new std::set<ConformanceTestSuite*>();
-  internal::OnShutdown(&DeleteConformanceTestSuiteSet);
-}
-
-static void InitConformanceTestSuiteSetOnce() {
-  ::google::protobuf::GoogleOnceInit(
-      &conformance_test_suite_set_init_,
-      &InitConformanceTestSuiteSet);
-}
-
-void AddTestSuite(ConformanceTestSuite* suite) {
-  InitConformanceTestSuiteSetOnce();
-  conformance_test_suite_set->insert(suite);
-}
-
-const std::set<ConformanceTestSuite*>& GetTestSuiteSet() {
-  InitConformanceTestSuiteSetOnce();
-  return *conformance_test_suite_set;
-}
-
 ConformanceTestSuite::ConformanceRequestSetting::ConformanceRequestSetting(
     ConformanceLevel level,
     conformance::WireFormat input_format,
diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h
index 8738735..d5c2f3d 100644
--- a/conformance/conformance_test.h
+++ b/conformance/conformance_test.h
@@ -62,6 +62,8 @@
 namespace google {
 namespace protobuf {
 
+class ConformanceTestSuite;
+
 class ConformanceTestRunner {
  public:
   virtual ~ConformanceTestRunner() {}
@@ -78,6 +80,54 @@
                        std::string* output) = 0;
 };
 
+// Test runner that spawns the process being tested and communicates with it
+// over a pipe.
+class ForkPipeRunner : public ConformanceTestRunner {
+ public:
+  static int Run(int argc, char *argv[],
+                 ConformanceTestSuite* suite);
+
+ private:
+  ForkPipeRunner(const std::string &executable)
+      : child_pid_(-1), executable_(executable) {}
+
+  virtual ~ForkPipeRunner() {}
+
+  void RunTest(const std::string& test_name,
+               const std::string& request,
+               std::string* response);
+
+  // TODO(haberman): make this work on Windows, instead of using these
+  // UNIX-specific APIs.
+  //
+  // There is a platform-agnostic API in
+  //    src/google/protobuf/compiler/subprocess.h
+  //
+  // However that API only supports sending a single message to the subprocess.
+  // We really want to be able to send messages and receive responses one at a
+  // time:
+  //
+  // 1. Spawning a new process for each test would take way too long for thousands
+  //    of tests and subprocesses like java that can take 100ms or more to start
+  //    up.
+  //
+  // 2. Sending all the tests in one big message and receiving all results in one
+  //    big message would take away our visibility about which test(s) caused a
+  //    crash or other fatal error.  It would also give us only a single failure
+  //    instead of all of them.
+  void SpawnTestProgram();
+
+  void CheckedWrite(int fd, const void *buf, size_t len);
+  bool TryRead(int fd, void *buf, size_t len);
+  void CheckedRead(int fd, void *buf, size_t len);
+
+  int write_fd_;
+  int read_fd_;
+  pid_t child_pid_;
+  std::string executable_;
+  std::string current_test_name_;
+};
+
 // Class representing the test suite itself.  To run it, implement your own
 // class derived from ConformanceTestRunner, class derived from
 // ConformanceTestSuite and then write code like:
@@ -89,28 +139,20 @@
 //      }
 //    };
 //
-//    // Force MyConformanceTestSuite to be added at dynamic initialization
-//    // time.
-//    struct StaticTestSuiteInitializer {
-//      StaticTestSuiteInitializer() {
-//        AddTestSuite(new MyConformanceTestSuite());
-//      }
-//    } static_test_suite_initializer;
-//
 //    class MyConformanceTestRunner : public ConformanceTestRunner {
 //     public:
+//      static int Run(int argc, char *argv[],
+//                 ConformanceTestSuite* suite);
+//
+//     private:
 //      virtual void RunTest(...) {
 //        // INSERT YOUR FRAMEWORK-SPECIFIC CODE HERE.
 //      }
 //    };
 //
 //    int main() {
-//      MyConformanceTestRunner runner;
-//      const std::set<ConformanceTestSuite*>& test_suite_set =
-//          ::google::protobuf::GetTestSuiteSet();
-//      for (auto suite : test_suite_set) {
-//        suite->RunSuite(&runner, &output);
-//      }
+//      MyConformanceTestSuite suite;
+//      MyConformanceTestRunner::Run(argc, argv, &suite);
 //    }
 //
 class ConformanceTestSuite {
@@ -259,9 +301,6 @@
   std::string type_url_;
 };
 
-void AddTestSuite(ConformanceTestSuite* suite);
-const std::set<ConformanceTestSuite*>& GetTestSuiteSet();
-
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/conformance/conformance_test_impl.cc b/conformance/conformance_test_impl.cc
index acd0f25..a884dea 100644
--- a/conformance/conformance_test_impl.cc
+++ b/conformance/conformance_test_impl.cc
@@ -2358,11 +2358,10 @@
       "");
 }
 
-struct StaticTestSuiteInitializer {
-  StaticTestSuiteInitializer() {
-    AddTestSuite(new ConformanceTestSuiteImpl());
-  }
-} static_test_suite_initializer;
-
 }  // namespace protobuf
 }  // namespace google
+
+int main(int argc, char *argv[]) {
+  google::protobuf::ConformanceTestSuiteImpl suite;
+  return google::protobuf::ForkPipeRunner::Run(argc, argv, &suite);
+}
diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc
index 3340f1c..9c37712 100644
--- a/conformance/conformance_test_runner.cc
+++ b/conformance/conformance_test_runner.cc
@@ -80,162 +80,31 @@
     exit(1); \
   }
 
-// Test runner that spawns the process being tested and communicates with it
-// over a pipe.
-class ForkPipeRunner : public google::protobuf::ConformanceTestRunner {
- public:
-  ForkPipeRunner(const std::string &executable)
-      : child_pid_(-1), executable_(executable) {}
+namespace google {
+namespace protobuf {
 
-  virtual ~ForkPipeRunner() {}
+void ParseFailureList(const char *filename,
+                      std::vector<string>* failure_list) {
+  std::ifstream infile(filename);
 
-  void RunTest(const std::string& test_name,
-               const std::string& request,
-               std::string* response) {
-    if (child_pid_ < 0) {
-      SpawnTestProgram();
-    }
-
-    current_test_name_ = test_name;
-
-    uint32_t len = request.size();
-    CheckedWrite(write_fd_, &len, sizeof(uint32_t));
-    CheckedWrite(write_fd_, request.c_str(), request.size());
-
-    if (!TryRead(read_fd_, &len, sizeof(uint32_t))) {
-      // We failed to read from the child, assume a crash and try to reap.
-      GOOGLE_LOG(INFO) << "Trying to reap child, pid=" << child_pid_;
-
-      int status;
-      waitpid(child_pid_, &status, WEXITED);
-
-      string error_msg;
-      if (WIFEXITED(status)) {
-        StringAppendF(&error_msg,
-                      "child exited, status=%d", WEXITSTATUS(status));
-      } else if (WIFSIGNALED(status)) {
-        StringAppendF(&error_msg,
-                      "child killed by signal %d", WTERMSIG(status));
-      }
-      GOOGLE_LOG(INFO) << error_msg;
-      child_pid_ = -1;
-
-      conformance::ConformanceResponse response_obj;
-      response_obj.set_runtime_error(error_msg);
-      response_obj.SerializeToString(response);
-      return;
-    }
-
-    response->resize(len);
-    CheckedRead(read_fd_, (void*)response->c_str(), len);
+  if (!infile.is_open()) {
+    fprintf(stderr, "Couldn't open failure list file: %s\n", filename);
+    exit(1);
   }
 
- private:
-  // TODO(haberman): make this work on Windows, instead of using these
-  // UNIX-specific APIs.
-  //
-  // There is a platform-agnostic API in
-  //    src/google/protobuf/compiler/subprocess.h
-  //
-  // However that API only supports sending a single message to the subprocess.
-  // We really want to be able to send messages and receive responses one at a
-  // time:
-  //
-  // 1. Spawning a new process for each test would take way too long for thousands
-  //    of tests and subprocesses like java that can take 100ms or more to start
-  //    up.
-  //
-  // 2. Sending all the tests in one big message and receiving all results in one
-  //    big message would take away our visibility about which test(s) caused a
-  //    crash or other fatal error.  It would also give us only a single failure
-  //    instead of all of them.
-  void SpawnTestProgram() {
-    int toproc_pipe_fd[2];
-    int fromproc_pipe_fd[2];
-    if (pipe(toproc_pipe_fd) < 0 || pipe(fromproc_pipe_fd) < 0) {
-      perror("pipe");
-      exit(1);
-    }
+  for (string line; getline(infile, line);) {
+    // Remove whitespace.
+    line.erase(std::remove_if(line.begin(), line.end(), ::isspace),
+               line.end());
 
-    pid_t pid = fork();
-    if (pid < 0) {
-      perror("fork");
-      exit(1);
-    }
+    // Remove comments.
+    line = line.substr(0, line.find("#"));
 
-    if (pid) {
-      // Parent.
-      CHECK_SYSCALL(close(toproc_pipe_fd[0]));
-      CHECK_SYSCALL(close(fromproc_pipe_fd[1]));
-      write_fd_ = toproc_pipe_fd[1];
-      read_fd_ = fromproc_pipe_fd[0];
-      child_pid_ = pid;
-    } else {
-      // Child.
-      CHECK_SYSCALL(close(STDIN_FILENO));
-      CHECK_SYSCALL(close(STDOUT_FILENO));
-      CHECK_SYSCALL(dup2(toproc_pipe_fd[0], STDIN_FILENO));
-      CHECK_SYSCALL(dup2(fromproc_pipe_fd[1], STDOUT_FILENO));
-
-      CHECK_SYSCALL(close(toproc_pipe_fd[0]));
-      CHECK_SYSCALL(close(fromproc_pipe_fd[1]));
-      CHECK_SYSCALL(close(toproc_pipe_fd[1]));
-      CHECK_SYSCALL(close(fromproc_pipe_fd[0]));
-
-      std::unique_ptr<char[]> executable(new char[executable_.size() + 1]);
-      memcpy(executable.get(), executable_.c_str(), executable_.size());
-      executable[executable_.size()] = '\0';
-
-      char *const argv[] = {executable.get(), NULL};
-      CHECK_SYSCALL(execv(executable.get(), argv));  // Never returns.
+    if (!line.empty()) {
+      failure_list->push_back(line);
     }
   }
-
-  void CheckedWrite(int fd, const void *buf, size_t len) {
-    if (write(fd, buf, len) != len) {
-      GOOGLE_LOG(FATAL) << current_test_name_
-                        << ": error writing to test program: "
-                        << strerror(errno);
-    }
-  }
-
-  bool TryRead(int fd, void *buf, size_t len) {
-    size_t ofs = 0;
-    while (len > 0) {
-      ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
-
-      if (bytes_read == 0) {
-        GOOGLE_LOG(ERROR) << current_test_name_
-                          << ": unexpected EOF from test program";
-        return false;
-      } else if (bytes_read < 0) {
-        GOOGLE_LOG(ERROR) << current_test_name_
-                          << ": error reading from test program: "
-                          << strerror(errno);
-        return false;
-      }
-
-      len -= bytes_read;
-      ofs += bytes_read;
-    }
-
-    return true;
-  }
-
-  void CheckedRead(int fd, void *buf, size_t len) {
-    if (!TryRead(fd, buf, len)) {
-      GOOGLE_LOG(FATAL) << current_test_name_
-                        << ": error reading from test program: "
-                        << strerror(errno);
-    }
-  }
-
-  int write_fd_;
-  int read_fd_;
-  pid_t child_pid_;
-  std::string executable_;
-  std::string current_test_name_;
-};
+}
 
 void UsageError() {
   fprintf(stderr,
@@ -263,33 +132,51 @@
   exit(1);
 }
 
-void ParseFailureList(const char *filename, std::vector<string>* failure_list) {
-  std::ifstream infile(filename);
-
-  if (!infile.is_open()) {
-    fprintf(stderr, "Couldn't open failure list file: %s\n", filename);
-    exit(1);
+void ForkPipeRunner::RunTest(
+    const std::string& test_name,
+    const std::string& request,
+    std::string* response) {
+  if (child_pid_ < 0) {
+    SpawnTestProgram();
   }
 
-  for (string line; getline(infile, line);) {
-    // Remove whitespace.
-    line.erase(std::remove_if(line.begin(), line.end(), ::isspace),
-               line.end());
+  current_test_name_ = test_name;
 
-    // Remove comments.
-    line = line.substr(0, line.find("#"));
+  uint32_t len = request.size();
+  CheckedWrite(write_fd_, &len, sizeof(uint32_t));
+  CheckedWrite(write_fd_, request.c_str(), request.size());
 
-    if (!line.empty()) {
-      failure_list->push_back(line);
+  if (!TryRead(read_fd_, &len, sizeof(uint32_t))) {
+    // We failed to read from the child, assume a crash and try to reap.
+    GOOGLE_LOG(INFO) << "Trying to reap child, pid=" << child_pid_;
+
+    int status;
+    waitpid(child_pid_, &status, WEXITED);
+
+    string error_msg;
+    if (WIFEXITED(status)) {
+      StringAppendF(&error_msg,
+                    "child exited, status=%d", WEXITSTATUS(status));
+    } else if (WIFSIGNALED(status)) {
+      StringAppendF(&error_msg,
+                    "child killed by signal %d", WTERMSIG(status));
     }
+    GOOGLE_LOG(INFO) << error_msg;
+    child_pid_ = -1;
+
+    conformance::ConformanceResponse response_obj;
+    response_obj.set_runtime_error(error_msg);
+    response_obj.SerializeToString(response);
+    return;
   }
+
+  response->resize(len);
+  CheckedRead(read_fd_, (void*)response->c_str(), len);
 }
 
-int main(int argc, char *argv[]) {
+int ForkPipeRunner::Run(
+    int argc, char *argv[], ConformanceTestSuite* suite) {
   char *program;
-  const std::set<ConformanceTestSuite*>& test_suite_set =
-      ::google::protobuf::GetTestSuiteSet();
-
   string failure_list_filename;
   std::vector<string> failure_list;
 
@@ -299,13 +186,9 @@
       failure_list_filename = argv[arg];
       ParseFailureList(argv[arg], &failure_list);
     } else if (strcmp(argv[arg], "--verbose") == 0) {
-      for (auto *suite : test_suite_set) {
-        suite->SetVerbose(true);
-      }
+      suite->SetVerbose(true);
     } else if (strcmp(argv[arg], "--enforce_recommended") == 0) {
-      for (auto suite : test_suite_set) {
-        suite->SetEnforceRecommended(true);
-      }
+      suite->SetEnforceRecommended(true);
     } else if (argv[arg][0] == '-') {
       fprintf(stderr, "Unknown option: %s\n", argv[arg]);
       UsageError();
@@ -318,18 +201,97 @@
     }
   }
 
-  for (auto suite : test_suite_set) {
-    suite->SetFailureList(failure_list_filename, failure_list);
-  }
+  suite->SetFailureList(failure_list_filename, failure_list);
   ForkPipeRunner runner(program);
 
   std::string output;
-  bool ok = true;
-  for (auto suite : test_suite_set) {
-    ok &= suite->RunSuite(&runner, &output);
-  }
+  bool ok =  suite->RunSuite(&runner, &output);
 
   fwrite(output.c_str(), 1, output.size(), stderr);
 
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
 }
+
+void ForkPipeRunner::SpawnTestProgram() {
+  int toproc_pipe_fd[2];
+  int fromproc_pipe_fd[2];
+  if (pipe(toproc_pipe_fd) < 0 || pipe(fromproc_pipe_fd) < 0) {
+    perror("pipe");
+    exit(1);
+  }
+
+  pid_t pid = fork();
+  if (pid < 0) {
+    perror("fork");
+    exit(1);
+  }
+
+  if (pid) {
+    // Parent.
+    CHECK_SYSCALL(close(toproc_pipe_fd[0]));
+    CHECK_SYSCALL(close(fromproc_pipe_fd[1]));
+    write_fd_ = toproc_pipe_fd[1];
+    read_fd_ = fromproc_pipe_fd[0];
+    child_pid_ = pid;
+  } else {
+    // Child.
+    CHECK_SYSCALL(close(STDIN_FILENO));
+    CHECK_SYSCALL(close(STDOUT_FILENO));
+    CHECK_SYSCALL(dup2(toproc_pipe_fd[0], STDIN_FILENO));
+    CHECK_SYSCALL(dup2(fromproc_pipe_fd[1], STDOUT_FILENO));
+
+    CHECK_SYSCALL(close(toproc_pipe_fd[0]));
+    CHECK_SYSCALL(close(fromproc_pipe_fd[1]));
+    CHECK_SYSCALL(close(toproc_pipe_fd[1]));
+    CHECK_SYSCALL(close(fromproc_pipe_fd[0]));
+
+    std::unique_ptr<char[]> executable(new char[executable_.size() + 1]);
+    memcpy(executable.get(), executable_.c_str(), executable_.size());
+    executable[executable_.size()] = '\0';
+
+    char *const argv[] = {executable.get(), NULL};
+    CHECK_SYSCALL(execv(executable.get(), argv));  // Never returns.
+  }
+}
+
+void ForkPipeRunner::CheckedWrite(int fd, const void *buf, size_t len) {
+  if (write(fd, buf, len) != len) {
+    GOOGLE_LOG(FATAL) << current_test_name_
+                      << ": error writing to test program: "
+                      << strerror(errno);
+  }
+}
+
+bool ForkPipeRunner::TryRead(int fd, void *buf, size_t len) {
+  size_t ofs = 0;
+  while (len > 0) {
+    ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
+
+    if (bytes_read == 0) {
+      GOOGLE_LOG(ERROR) << current_test_name_
+                        << ": unexpected EOF from test program";
+      return false;
+    } else if (bytes_read < 0) {
+      GOOGLE_LOG(ERROR) << current_test_name_
+                        << ": error reading from test program: "
+                        << strerror(errno);
+      return false;
+    }
+
+    len -= bytes_read;
+    ofs += bytes_read;
+  }
+
+  return true;
+}
+
+void ForkPipeRunner::CheckedRead(int fd, void *buf, size_t len) {
+  if (!TryRead(fd, buf, len)) {
+    GOOGLE_LOG(FATAL) << current_test_name_
+                      << ": error reading from test program: "
+                      << strerror(errno);
+  }
+}
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt
index bb32ace..17e0fda 100644
--- a/conformance/failure_list_php_c.txt
+++ b/conformance/failure_list_php_c.txt
@@ -93,8 +93,6 @@
 Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput
 Required.Proto3.JsonInput.ValueAcceptList.JsonOutput
 Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput
-Required.Proto3.JsonInput.ValueAcceptListWithNull.JsonOutput
-Required.Proto3.JsonInput.ValueAcceptListWithNull.ProtobufOutput
 Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput
 Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput
 Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index 1bab135..53b4970 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -133,3 +133,9 @@
 Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
 Required.TimestampProtoInputTooLarge.JsonOutput
 Required.TimestampProtoInputTooSmall.JsonOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonFalse.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonNull.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonNumber.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonString.ProtobufOutput
+Required.Proto3.JsonInput.IgnoreUnknownJsonTrue.ProtobufOutput
diff --git a/docs/options.md b/docs/options.md
index 70db4d6..700fef6 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -14,7 +14,7 @@
 ## Existing Registered Extensions
 
 1. C# port of protocol buffers
-   * Website: http://github.com/jskeet/dotnet-protobufs
+   * Website: https://github.com/jskeet/protobuf-csharp-port
    * Extensions: 1000
 
 1. Perl/XS port of protocol buffers
@@ -50,7 +50,7 @@
    * Extensions: 1008
 
 1. Goby Underwater Autonomy Project
-   * Website: https://launchpad.net/goby
+   * Website: https://github.com/GobySoft/goby
    * Extensions: 1009
 
 1. Nanopb
@@ -62,7 +62,7 @@
    * Extensions: 1011
 
 1. Dynamic Compact Control Language
-   * Website: https://launchpad.net/dccl
+   * Website: http://github.com/GobySoft/dccl
    * Extensions: 1012
 
 1. ScaleOut StateServer® Native C++ API
@@ -188,3 +188,9 @@
 1. Netifi Proteus
    * Website: https://github.com/netifi-proteus
    * Extensions: 1057
+
+1. CGSN Mooring Project
+   * Website: https://bitbucket.org/ooicgsn/cgsn-mooring
+   * Extensions: 1058
+   
+
diff --git a/java/README.md b/java/README.md
index 5e4fb8b..def4fd9 100644
--- a/java/README.md
+++ b/java/README.md
@@ -13,13 +13,17 @@
     $ protoc --java_out=${OUTPUT_DIR} path/to/your/proto/file
 
 Include the generated Java files in your project and add a dependency on the
-protobuf Java runtime. If you are using Maven, use the following:
+protobuf Java runtime.
+
+### Maven
+
+If you are using Maven, use the following:
 
 ```xml
 <dependency>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-java</artifactId>
-  <version>3.5.1</version>
+  <version>3.6.1</version>
 </dependency>
 ```
 
@@ -33,10 +37,18 @@
 <dependency>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-java-util</artifactId>
-  <version>3.5.1</version>
+  <version>3.6.1</version>
 </dependency>
 ```
 
+### Gradle
+
+If you are using Gradle, add the following to your `build.gradle` file's dependencies:
+```
+    compile 'com.google.protobuf:protobuf-java:3.6.1'
+```
+Again, be sure to check that the version number maches (or is newer than) the version number of protoc that you are using.
+
 ### Use Java Protocol Buffers on Android
 
 For Android users, it's recommended to use protobuf Java Lite runtime because
diff --git a/kokoro/release/collect_all_artifacts.cfg b/kokoro/release/collect_all_artifacts.cfg
new file mode 100644
index 0000000..3da1a7c
--- /dev/null
+++ b/kokoro/release/collect_all_artifacts.cfg
@@ -0,0 +1,7 @@
+build_file: "protobuf/kokoro/release/collect_all_artifacts.sh"
+
+action {
+  define_artifacts {
+    regex: "github/protobuf/artifacts/**"
+  }
+}
diff --git a/kokoro/release/collect_all_artifacts.sh b/kokoro/release/collect_all_artifacts.sh
new file mode 100755
index 0000000..0023937
--- /dev/null
+++ b/kokoro/release/collect_all_artifacts.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+set -ex
+
+# Change to repo root.
+cd $(dirname $0)/../..
+
+# Initialize any submodules.
+git submodule update --init --recursive
+
+# The directory with all resulting artifacts
+mkdir -p artifacts
+
+# Artifacts from all predecessor jobs get copied to this directory by kokoro
+INPUT_ARTIFACTS_DIR="${KOKORO_GFILE_DIR}/github/protobuf"
+
+# TODO(jtattermusch): remove listing the files, but for now it make it easier
+# to iterate on the script.
+ls -R ${INPUT_ARTIFACTS_DIR}
+
+# ====================================
+# Copy to expose all the artifacts from the predecessor jobs to the output
+# TODO(jtattermusch): the directory layout of the artifact builds is pretty messy,
+# so will be the output artifacts of this job.
+cp -r ${INPUT_ARTIFACTS_DIR}/* artifacts
+
+# ====================================
+# Build Google.Protobuf.Tools C# nuget
+# The reason it's being done in this script is that we need access to protoc binaries
+# built on multiple platform (the build is performed by the "build artifact" step)
+# and adding and extra chained build just for building the Google.Protobuf.Tools
+# nuget seems like an overkill.
+cd csharp
+mkdir -p protoc/windows_x86
+mkdir -p protoc/windows_x64
+cp ${INPUT_ARTIFACTS_DIR}/build32/Release/protoc.exe protoc/windows_x86/protoc.exe
+cp ${INPUT_ARTIFACTS_DIR}/build64/Release/protoc.exe protoc/windows_x64/protoc.exe
+
+mkdir -p protoc/linux_x86
+mkdir -p protoc/linux_x64
+# Because of maven unrelated reasonse the linux protoc binaries have a dummy .exe extension.
+# For the Google.Protobuf.Tools nuget, we don't want that expection, so we just remove it.
+cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_32/protoc.exe protoc/linux_x86/protoc
+cp ${INPUT_ARTIFACTS_DIR}/protoc-artifacts/target/linux/x86_64/protoc.exe protoc/linux_x64/protoc
+
+mkdir -p protoc/macosx_x86
+mkdir -p protoc/macosx_x64
+cp ${INPUT_ARTIFACTS_DIR}/build32/src/protoc protoc/macosx_x86/protoc
+cp ${INPUT_ARTIFACTS_DIR}/build64/src/protoc protoc/macosx_x64/protoc
+
+# Install nuget (will also install  mono)
+# TODO(jtattermusch): use "mono:5.14" docker image instead so we don't have to apt-get install
+sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+sudo apt install apt-transport-https
+echo "deb https://download.mono-project.com/repo/ubuntu stable-trusty main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
+sudo apt update
+sudo apt-get install -y nuget
+
+nuget pack Google.Protobuf.Tools.nuspec
+
+# Copy the nupkg to the output artifacts
+cp Google.Protobuf.Tools.*.nupkg ../artifacts
diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h
index 9cb36dc..a84feec 100644
--- a/php/ext/google/protobuf/protobuf.h
+++ b/php/ext/google/protobuf/protobuf.h
@@ -138,7 +138,8 @@
     INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
                         LOWWERNAME##_methods);                               \
     LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
-    LOWWERNAME##_type->create_object = message_create;
+    LOWWERNAME##_type->create_object = message_create;                       \
+    zend_do_inheritance(LOWWERNAME##_type, message_type TSRMLS_CC);
 #define PHP_PROTO_INIT_SUBMSGCLASS_END \
   }
 
@@ -404,7 +405,7 @@
     INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
                         LOWWERNAME##_methods);                               \
     LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
-    LOWWERNAME##_type->create_object = message_create;
+    zend_do_inheritance(LOWWERNAME##_type, message_type TSRMLS_CC);
 #define PHP_PROTO_INIT_SUBMSGCLASS_END \
   }
 
diff --git a/php/tests/well_known_test.php b/php/tests/well_known_test.php
index 9f2661f..6a788df 100644
--- a/php/tests/well_known_test.php
+++ b/php/tests/well_known_test.php
@@ -42,6 +42,7 @@
     public function testEmpty()
     {
         $msg = new GPBEmpty();
+        $this->assertTrue($msg instanceof \Google\Protobuf\Internal\Message);
     }
 
     public function testImportDescriptorProto()
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index cf0fa45..9c52116 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -76,6 +76,18 @@
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
     const TypeInfo* typeinfo, const google::protobuf::Type& type,
+    strings::ByteSink* output, ErrorListener* listener,
+    const ProtoStreamObjectWriter::Options& options)
+    : ProtoWriter(typeinfo, type, output, listener),
+      master_type_(type),
+      current_(nullptr),
+      options_(options) {
+  set_ignore_unknown_fields(options_.ignore_unknown_fields);
+  set_use_lower_camel_for_enums(options.use_lower_camel_for_enums);
+}
+
+ProtoStreamObjectWriter::ProtoStreamObjectWriter(
+    const TypeInfo* typeinfo, const google::protobuf::Type& type,
     strings::ByteSink* output, ErrorListener* listener)
     : ProtoWriter(typeinfo, type, output, listener),
       master_type_(type),
@@ -343,7 +355,7 @@
   // Create our object writer and initialize it with the first StartObject
   // call.
   ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_,
-                                        parent_->listener()));
+                                        parent_->listener(), parent_->options_));
 
   // Don't call StartObject() for well-known types yet. Depending on the
   // type of actual data, we may not need to call StartObject(). For
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index f865cc1..fe8170d 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -330,6 +330,11 @@
                           const google::protobuf::Type& type,
                           strings::ByteSink* output, ErrorListener* listener);
 
+ ProtoStreamObjectWriter(const TypeInfo* typeinfo,
+                          const google::protobuf::Type& type,
+                          strings::ByteSink* output, ErrorListener* listener,
+                          const ProtoStreamObjectWriter::Options& options);
+
   // Returns true if the field is a map.
   inline bool IsMap(const google::protobuf::Field& field);
 
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index cbfc7ad..125d4d4 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -56,6 +56,7 @@
 using proto3::TestMap;
 using proto3::TestMessage;
 using proto3::TestOneof;
+using proto3::TestAny;
 
 static const char kTypeUrlPrefix[] = "type.googleapis.com";
 
@@ -357,6 +358,28 @@
   EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
 }
 
+TEST_F(JsonUtilTest, TestParsingUnknownAnyFields) {
+  string input =
+      "{\n"
+      "  \"value\": {\n"
+      "    \"@type\": \"type.googleapis.com/proto3.TestMessage\",\n"
+      "    \"unknown_field\": \"UNKOWN_VALUE\",\n"
+      "    \"string_value\": \"expected_value\"\n"
+      "  }\n"
+      "}";
+      
+  TestAny m;
+  JsonParseOptions options;
+  EXPECT_FALSE(FromJson(input, &m, options));
+
+  options.ignore_unknown_fields = true;
+  EXPECT_TRUE(FromJson(input, &m, options));
+
+  TestMessage t;
+  EXPECT_TRUE(m.value().UnpackTo(&t));
+  EXPECT_EQ("expected_value", t.string_value());
+}
+
 TEST_F(JsonUtilTest, TestParsingUnknownEnumsProto2) {
   string input =
       "{\n"