Browse Source

Merge pull request #4924 from xfxyjwf/3.6.x

Cherry-pick master build fixes and kokoro changes to 3.6.x
Feng Xiao 7 years ago
parent
commit
d85ffdce41

+ 0 - 1
.gitignore

@@ -47,7 +47,6 @@ any_test.pb.*
 map*unittest.pb.*
 map*unittest.pb.*
 unittest*.pb.*
 unittest*.pb.*
 cpp_test*.pb.*
 cpp_test*.pb.*
-src/google/protobuf/compiler/js/well_known_types_embed.cc
 src/google/protobuf/util/**/*.pb.cc
 src/google/protobuf/util/**/*.pb.cc
 src/google/protobuf/util/**/*.pb.h
 src/google/protobuf/util/**/*.pb.h
 
 

+ 0 - 18
BUILD

@@ -257,24 +257,6 @@ internal_copied_filegroup(
 # Protocol Buffers Compiler
 # Protocol Buffers Compiler
 ################################################################################
 ################################################################################
 
 
-cc_binary(
-    name = "js_embed",
-    srcs = ["src/google/protobuf/compiler/js/embed.cc"],
-    visibility = ["//visibility:public"],
-)
-
-genrule(
-    name = "generate_js_well_known_types_embed",
-    srcs = [
-        "src/google/protobuf/compiler/js/well_known_types/any.js",
-        "src/google/protobuf/compiler/js/well_known_types/struct.js",
-        "src/google/protobuf/compiler/js/well_known_types/timestamp.js",
-    ],
-    outs = ["src/google/protobuf/compiler/js/well_known_types_embed.cc"],
-    cmd = "$(location :js_embed) $(SRCS) > $@",
-    tools = [":js_embed"],
-)
-
 cc_library(
 cc_library(
     name = "protoc_lib",
     name = "protoc_lib",
     srcs = [
     srcs = [

+ 5 - 0
autogen.sh

@@ -28,6 +28,11 @@ fi
 
 
 set -ex
 set -ex
 
 
+# The absence of a m4 directory in googletest causes autoreconf to fail when
+# building under the CentOS docker image. It's a warning in regular build on
+# Ubuntu/gLinux as well.
+mkdir -p third_party/googletest/m4
+
 # TODO(kenton):  Remove the ",no-obsolete" part and fix the resulting warnings.
 # TODO(kenton):  Remove the ",no-obsolete" part and fix the resulting warnings.
 autoreconf -f -i -Wall,no-obsolete
 autoreconf -f -i -Wall,no-obsolete
 
 

+ 1 - 0
benchmarks/Makefile.am

@@ -109,6 +109,7 @@ cpp_benchmark_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(top_srcdir)/thi
 # so a direct "make test_cpp" could fail if parallel enough.
 # so a direct "make test_cpp" could fail if parallel enough.
 # See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually
 # See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually
 cpp/cpp_benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a
 cpp/cpp_benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a
+cpp/benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a
 nodist_cpp_benchmark_SOURCES =                                             \
 nodist_cpp_benchmark_SOURCES =                                             \
 	$(benchmarks_protoc_outputs)                                             \
 	$(benchmarks_protoc_outputs)                                             \
 	$(benchmarks_protoc_outputs_proto2)                                      \
 	$(benchmarks_protoc_outputs_proto2)                                      \

+ 4 - 10
cmake/libprotoc.cmake

@@ -161,17 +161,11 @@ set(libprotoc_headers
   ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.h
 )
 )
 
 
-set(js_well_known_types_sources
-  ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types/any.js
-  ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types/struct.js
-  ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types/timestamp.js
-)
-add_executable(js_embed ${protobuf_source_dir}/src/google/protobuf/compiler/js/embed.cc)
-add_custom_command(
-  OUTPUT ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types_embed.cc
-  DEPENDS js_embed ${js_well_known_types_sources}
-  COMMAND js_embed ${js_well_known_types_sources} > ${protobuf_source_dir}/src/google/protobuf/compiler/js/well_known_types_embed.cc
+if (MSVC)
+set(libprotoc_rc_files
+  ${CMAKE_CURRENT_BINARY_DIR}/version.rc
 )
 )
+endif()
 
 
 add_library(libprotoc ${protobuf_SHARED_OR_STATIC}
 add_library(libprotoc ${protobuf_SHARED_OR_STATIC}
   ${libprotoc_files} ${libprotoc_headers})
   ${libprotoc_files} ${libprotoc_headers})

+ 0 - 2
conformance/Makefile.am

@@ -279,8 +279,6 @@ $(protoc_outputs): protoc_middleman
 
 
 $(other_language_protoc_outputs): protoc_middleman
 $(other_language_protoc_outputs): protoc_middleman
 
 
-BUILT_SOURCES = $(protoc_outputs) $(other_language_protoc_outputs)
-
 CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java javac_middleman_lite conformance-java-lite conformance-csharp conformance-php conformance-php-c $(other_language_protoc_outputs)
 CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java javac_middleman_lite conformance-java-lite conformance-csharp conformance-php conformance-php-c $(other_language_protoc_outputs)
 
 
 MAINTAINERCLEANFILES =   \
 MAINTAINERCLEANFILES =   \

+ 2 - 2
conformance/conformance_php.php

@@ -6,8 +6,8 @@ require_once("Conformance/ConformanceRequest.php");
 require_once("Protobuf_test_messages/Proto3/ForeignMessage.php");
 require_once("Protobuf_test_messages/Proto3/ForeignMessage.php");
 require_once("Protobuf_test_messages/Proto3/ForeignEnum.php");
 require_once("Protobuf_test_messages/Proto3/ForeignEnum.php");
 require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3.php");
 require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3.php");
-require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedMessage.php");
-require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedEnum.php");
+require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedMessage.php");
+require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedEnum.php");
 
 
 require_once("GPBMetadata/Conformance.php");
 require_once("GPBMetadata/Conformance.php");
 require_once("GPBMetadata/Google/Protobuf/TestMessagesProto3.php");
 require_once("GPBMetadata/Google/Protobuf/TestMessagesProto3.php");

+ 1 - 1
examples/list_people_test.go

@@ -34,7 +34,7 @@ func TestWritePersonWritesPerson(t *testing.T) {
 
 
 func TestListPeopleWritesList(t *testing.T) {
 func TestListPeopleWritesList(t *testing.T) {
 	buf := new(bytes.Buffer)
 	buf := new(bytes.Buffer)
-	in := pb.AddressBook{[]*pb.Person{
+	in := pb.AddressBook{People: []*pb.Person {
 		{
 		{
 			Name:  "John Doe",
 			Name:  "John Doe",
 			Id:    101,
 			Id:    101,

+ 2 - 0
kokoro/linux/build_and_run_docker.sh

@@ -35,6 +35,8 @@ echo $git_root
 docker run \
 docker run \
   "$@" \
   "$@" \
   -e CCACHE_DIR=$CCACHE_DIR \
   -e CCACHE_DIR=$CCACHE_DIR \
+  -e KOKORO_BUILD_NUMBER=$KOKORO_BUILD_NUMBER \
+  -e KOKORO_BUILD_ID=$KOKORO_BUILD_ID \
   -e EXTERNAL_GIT_ROOT="/var/local/kokoro/protobuf" \
   -e EXTERNAL_GIT_ROOT="/var/local/kokoro/protobuf" \
   -e TEST_SET="$TEST_SET" \
   -e TEST_SET="$TEST_SET" \
   -e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \
   -e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \

+ 11 - 3
kokoro/linux/cpp_distcheck/build.sh

@@ -5,7 +5,15 @@
 # Change to repo root
 # Change to repo root
 cd $(dirname $0)/../../..
 cd $(dirname $0)/../../..
 
 
-# Prepare worker environment to run tests
-source kokoro/linux/prepare_build_linux_rc
-
 ./tests.sh cpp_distcheck
 ./tests.sh cpp_distcheck
+
+# Run tests under release docker image.
+DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
+docker pull $DOCKER_IMAGE_NAME
+
+docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \
+  bash -l /var/local/protobuf/tests.sh cpp || FAILED="true"
+
+if [ "$FAILED" = "true" ]; then
+  exit 1
+fi

+ 6 - 2
kokoro/linux/pull_request_in_docker.sh

@@ -5,7 +5,7 @@
 
 
 WORKSPACE_BASE=`pwd`
 WORKSPACE_BASE=`pwd`
 MY_DIR="$(dirname "$0")"
 MY_DIR="$(dirname "$0")"
-TEST_SCRIPT=$MY_DIR/../../tests.sh
+TEST_SCRIPT=./tests.sh
 BUILD_DIR=/tmp/protobuf
 BUILD_DIR=/tmp/protobuf
 
 
 set -e  # exit immediately on error
 set -e  # exit immediately on error
@@ -53,7 +53,7 @@ $TIME_CMD $TEST_SCRIPT cpp > >(tee $CPP_STDOUT) 2> >(tee $CPP_STDERR >&2)
 
 
 parallel --results $LOG_OUTPUT_DIR --joblog $OUTPUT_DIR/joblog $TEST_SCRIPT ::: \
 parallel --results $LOG_OUTPUT_DIR --joblog $OUTPUT_DIR/joblog $TEST_SCRIPT ::: \
   $TEST_SET \
   $TEST_SET \
-  || true  # Process test results even if tests fail.
+  || FAILED="true"  # Process test results even if tests fail.
 
 
 cat $OUTPUT_DIR/joblog
 cat $OUTPUT_DIR/joblog
 
 
@@ -67,3 +67,7 @@ TESTOUTPUT_XML_FILE=$COPY_FROM_DOCKER/sponge_log.xml
 python $MY_DIR/make_test_output.py $OUTPUT_DIR > $TESTOUTPUT_XML_FILE
 python $MY_DIR/make_test_output.py $OUTPUT_DIR > $TESTOUTPUT_XML_FILE
 
 
 ls -l $TESTOUTPUT_XML_FILE
 ls -l $TESTOUTPUT_XML_FILE
+
+if [ "$FAILED" == "true" ]; then
+	exit 1
+fi

+ 36 - 0
kokoro/release/protoc/linux/build.sh

@@ -0,0 +1,36 @@
+#!/bin/bash
+
+set -x
+
+# Change to repo root.
+cd $(dirname $0)/../../../..
+
+# Initialize any submodules.
+git submodule update --init --recursive
+
+# Generate the configure script.
+./autogen.sh
+
+# Use docker image to build linux artifacts.
+DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
+docker pull $DOCKER_IMAGE_NAME
+
+docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \
+    bash -l /var/local/protobuf/protoc-artifacts/build-protoc.sh \
+    linux x86_64 protoc || {
+  echo "Failed to build protoc for linux + x86_64."
+  exit 1
+}
+
+docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \
+    bash -l /var/local/protobuf/protoc-artifacts/build-protoc.sh \
+    linux x86_32 protoc || {
+  echo "Failed to build protoc for linux + x86_32."
+  exit 1
+}
+
+# Cross-build for some architectures.
+# TODO(xiaofeng): It currently fails with "machine `aarch64' not recognized"
+# error.
+# sudo apt install -y g++-aarch64-linux-gnu
+# protoc-artifacts/build-protoc.sh linux aarch_64 protoc

+ 7 - 0
kokoro/release/protoc/linux/release.cfg

@@ -0,0 +1,7 @@
+build_file: "protobuf/kokoro/release/protoc/linux/build.sh"
+
+action {
+  define_artifacts {
+    regex: "**/protoc.exe"
+  }
+}

+ 1 - 0
php/ext/google/protobuf/message.c

@@ -283,6 +283,7 @@ void build_class_from_descriptor(
 // -----------------------------------------------------------------------------
 // -----------------------------------------------------------------------------
 
 
 void Message_construct(zval* msg, zval* array_wrapper) {
 void Message_construct(zval* msg, zval* array_wrapper) {
+  TSRMLS_FETCH();
   zend_class_entry* ce = Z_OBJCE_P(msg);
   zend_class_entry* ce = Z_OBJCE_P(msg);
   MessageHeader* intern = NULL;
   MessageHeader* intern = NULL;
   if (EXPECTED(class_added(ce))) {
   if (EXPECTED(class_added(ce))) {

+ 13 - 18
php/src/Google/Protobuf/Internal/MapField.php

@@ -156,15 +156,22 @@ class MapField implements \ArrayAccess, \IteratorAggregate, \Countable
         $this->checkKey($this->key_type, $key);
         $this->checkKey($this->key_type, $key);
 
 
         switch ($this->value_type) {
         switch ($this->value_type) {
+            case GPBType::SFIXED32:
+            case GPBType::SINT32:
             case GPBType::INT32:
             case GPBType::INT32:
+            case GPBType::ENUM:
                 GPBUtil::checkInt32($value);
                 GPBUtil::checkInt32($value);
                 break;
                 break;
+            case GPBType::FIXED32:
             case GPBType::UINT32:
             case GPBType::UINT32:
                 GPBUtil::checkUint32($value);
                 GPBUtil::checkUint32($value);
                 break;
                 break;
+            case GPBType::SFIXED64:
+            case GPBType::SINT64:
             case GPBType::INT64:
             case GPBType::INT64:
                 GPBUtil::checkInt64($value);
                 GPBUtil::checkInt64($value);
                 break;
                 break;
+            case GPBType::FIXED64:
             case GPBType::UINT64:
             case GPBType::UINT64:
                 GPBUtil::checkUint64($value);
                 GPBUtil::checkUint64($value);
                 break;
                 break;
@@ -249,36 +256,24 @@ class MapField implements \ArrayAccess, \IteratorAggregate, \Countable
     private function checkKey($key_type, &$key)
     private function checkKey($key_type, &$key)
     {
     {
         switch ($key_type) {
         switch ($key_type) {
+            case GPBType::SFIXED32:
+            case GPBType::SINT32:
             case GPBType::INT32:
             case GPBType::INT32:
                 GPBUtil::checkInt32($key);
                 GPBUtil::checkInt32($key);
                 break;
                 break;
+            case GPBType::FIXED32:
             case GPBType::UINT32:
             case GPBType::UINT32:
                 GPBUtil::checkUint32($key);
                 GPBUtil::checkUint32($key);
                 break;
                 break;
+            case GPBType::SFIXED64:
+            case GPBType::SINT64:
             case GPBType::INT64:
             case GPBType::INT64:
                 GPBUtil::checkInt64($key);
                 GPBUtil::checkInt64($key);
                 break;
                 break;
-            case GPBType::UINT64:
-                GPBUtil::checkUint64($key);
-                break;
             case GPBType::FIXED64:
             case GPBType::FIXED64:
+            case GPBType::UINT64:
                 GPBUtil::checkUint64($key);
                 GPBUtil::checkUint64($key);
                 break;
                 break;
-            case GPBType::FIXED32:
-                GPBUtil::checkUint32($key);
-                break;
-            case GPBType::SFIXED64:
-                GPBUtil::checkInt64($key);
-                break;
-            case GPBType::SFIXED32:
-                GPBUtil::checkInt32($key);
-                break;
-            case GPBType::SINT64:
-                GPBUtil::checkInt64($key);
-                break;
-            case GPBType::SINT32:
-                GPBUtil::checkInt32($key);
-                break;
             case GPBType::BOOL:
             case GPBType::BOOL:
                 GPBUtil::checkBool($key);
                 GPBUtil::checkBool($key);
                 break;
                 break;

+ 10 - 0
php/src/Google/Protobuf/Internal/RepeatedField.php

@@ -141,15 +141,22 @@ class RepeatedField implements \ArrayAccess, \IteratorAggregate, \Countable
     public function offsetSet($offset, $value)
     public function offsetSet($offset, $value)
     {
     {
         switch ($this->type) {
         switch ($this->type) {
+            case GPBType::SFIXED32:
+            case GPBType::SINT32:
             case GPBType::INT32:
             case GPBType::INT32:
+            case GPBType::ENUM:
                 GPBUtil::checkInt32($value);
                 GPBUtil::checkInt32($value);
                 break;
                 break;
+            case GPBType::FIXED32:
             case GPBType::UINT32:
             case GPBType::UINT32:
                 GPBUtil::checkUint32($value);
                 GPBUtil::checkUint32($value);
                 break;
                 break;
+            case GPBType::SFIXED64:
+            case GPBType::SINT64:
             case GPBType::INT64:
             case GPBType::INT64:
                 GPBUtil::checkInt64($value);
                 GPBUtil::checkInt64($value);
                 break;
                 break;
+            case GPBType::FIXED64:
             case GPBType::UINT64:
             case GPBType::UINT64:
                 GPBUtil::checkUint64($value);
                 GPBUtil::checkUint64($value);
                 break;
                 break;
@@ -162,6 +169,9 @@ class RepeatedField implements \ArrayAccess, \IteratorAggregate, \Countable
             case GPBType::BOOL:
             case GPBType::BOOL:
                 GPBUtil::checkBool($value);
                 GPBUtil::checkBool($value);
                 break;
                 break;
+            case GPBType::BYTES:
+                GPBUtil::checkString($value, false);
+                break;
             case GPBType::STRING:
             case GPBType::STRING:
                 GPBUtil::checkString($value, true);
                 GPBUtil::checkString($value, true);
                 break;
                 break;

+ 2 - 0
php/tests/compatibility_test.sh

@@ -122,6 +122,8 @@ composer install
 tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php )
 tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php )
 sed -i.bak '/php_implementation_test.php/d' phpunit.xml
 sed -i.bak '/php_implementation_test.php/d' phpunit.xml
 sed -i.bak '/generated_phpdoc_test.php/d' phpunit.xml
 sed -i.bak '/generated_phpdoc_test.php/d' phpunit.xml
+sed -i.bak 's/generated_phpdoc_test.php//g' tests/test.sh
+sed -i.bak '/memory_leak_test.php/d' tests/test.sh
 for t in "${tests[@]}"
 for t in "${tests[@]}"
 do
 do
   remove_error_test tests/$t
   remove_error_test tests/$t

+ 1 - 1
php/tests/test.sh

@@ -14,7 +14,7 @@ set -e
 phpize && ./configure CFLAGS='-g -O0' && make
 phpize && ./configure CFLAGS='-g -O0' && make
 popd
 popd
 
 
-tests=( array_test.php encode_decode_test.php generated_class_test.php generated_phpdoc_test.php map_field_test.php well_known_test.php generated_service_test.php descriptors_test.php )
+tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php descriptors_test.php )
 
 
 for t in "${tests[@]}"
 for t in "${tests[@]}"
 do
 do

+ 8 - 9
protoc-artifacts/Dockerfile

@@ -1,4 +1,4 @@
-FROM centos:6.6
+FROM centos:6.9
 
 
 RUN yum install -y git \
 RUN yum install -y git \
                    tar \
                    tar \
@@ -28,15 +28,14 @@ RUN wget -q http://apache.cs.utah.edu/maven/maven-3/3.3.9/binaries/apache-maven-
     tar xz -C /var/local
     tar xz -C /var/local
 ENV PATH /var/local/apache-maven-3.3.9/bin:$PATH
 ENV PATH /var/local/apache-maven-3.3.9/bin:$PATH
 
 
-# Install GCC 4.7 to support -static-libstdc++
-RUN wget http://people.centos.org/tru/devtools-1.1/devtools-1.1.repo -P /etc/yum.repos.d && \
-    bash -c 'echo "enabled=1" >> /etc/yum.repos.d/devtools-1.1.repo' && \
-    bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-1.1.repo > /etc/yum.repos.d/devtools-i386-1.1.repo" && \
-    sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-1.1.repo && \
+# Install GCC 4.8 to support -static-libstdc++
+RUN wget http://people.centos.org/tru/devtools-2/devtools-2.repo -P /etc/yum.repos.d && \
+    bash -c 'echo "enabled=1" >> /etc/yum.repos.d/devtools-2.repo' && \
+    bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-2.repo > /etc/yum.repos.d/devtools-i386-2.repo" && \
+    sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-2.repo && \
     rpm --rebuilddb && \
     rpm --rebuilddb && \
-    yum install -y devtoolset-1.1 \
-                   devtoolset-1.1-libstdc++-devel \
-                   devtoolset-1.1-libstdc++-devel.i686 && \
+    yum install -y devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils devtoolset-2-libstdc++-devel \
+                   devtoolset-2-gcc.i686 devtoolset-2-gcc-c++.i686 devtoolset-2-binutils.i686 devtoolset-2-libstdc++-devel.i686 && \
     yum clean all
     yum clean all
 
 
 COPY scl-enable-devtoolset.sh /var/local/
 COPY scl-enable-devtoolset.sh /var/local/

+ 101 - 121
protoc-artifacts/README.md

@@ -7,13 +7,31 @@ build and publish a ``protoc`` executable (a.k.a. artifact) to Maven
 repositories. The artifact can be used by build automation tools so that users
 repositories. The artifact can be used by build automation tools so that users
 would not need to compile and install ``protoc`` for their systems.
 would not need to compile and install ``protoc`` for their systems.
 
 
+If you would like us to publish protoc artifact for a new platform, please send
+us a pull request to add support for the new platform. You would need to change
+the following files:
+
+* [build-protoc.sh](build-protoc.sh): script to cross-build the protoc for your
+  platform.
+* [pom.xml](pom.xml): script to upload artifacts to maven.
+* [build-zip.sh](build-zip.sh): script to package published maven artifacts in
+  our release page.
+
+## Maven Location
+The published protoc artifacts are available on Maven here:
+
+    http://central.maven.org/maven2/com/google/protobuf/protoc/
+
 ## Versioning
 ## Versioning
 The version of the ``protoc`` artifact must be the same as the version of the
 The version of the ``protoc`` artifact must be the same as the version of the
 Protobuf project.
 Protobuf project.
 
 
 ## Artifact name
 ## Artifact name
 The name of a published ``protoc`` artifact is in the following format:
 The name of a published ``protoc`` artifact is in the following format:
-``protoc-<version>-<os>-<arch>.exe``, e.g., ``protoc-3.0.0-alpha-3-windows-x86_64.exe``.
+``protoc-<version>-<os>-<arch>.exe``, e.g., ``protoc-3.6.1-linux-x86_64.exe``.
+
+Note that artifacts for linux/macos also have the `.exe` suffix but they are
+not windows binaries.
 
 
 ## System requirement
 ## System requirement
 Install [Apache Maven](http://maven.apache.org/) if you don't have it.
 Install [Apache Maven](http://maven.apache.org/) if you don't have it.
@@ -29,98 +47,116 @@ generate the configure script.
 
 
 Under the protobuf project directory:
 Under the protobuf project directory:
 
 
+
+```
+$ ./autogen.sh
+```
+
+### Build the artifact for each platform
+
+Run the build-protoc.sh script under this protoc-artifacts directory to build the protoc
+artifact for each platform.  For example:
+
 ```
 ```
-$ ./autogen.sh && ./configure && make
+$ cd protoc-artifacts
+$ ./build-protoc.sh linux x86_64 protoc
 ```
 ```
 
 
-## To install artifacts locally
-The following command will install the ``protoc`` artifact to your local Maven repository.
+The above command will produce a `target/linux/x86_64/protoc` binary under the
+protoc-artifacts directory.
+
+For a list of supported platforms, see the comments in the build-protoc.sh
+script. We only use this script to build artifacts on Ubuntu and MacOS (both
+with x86_64, and do cross-compilation for other platforms.
+
+### Tips for building for Linux
+We build on Centos 6.9 to provide a good compatibility for not very new
+systems. We have provided a ``Dockerfile`` under this directory to build the
+environment. It has been tested with Docker 1.6.1.
+
+To build a image:
+
 ```
 ```
-$ mvn install
+$ docker build -t protoc-artifacts .
 ```
 ```
 
 
-## Cross-compilation
-The Maven script will try to detect the OS and the architecture from Java
-system properties. It's possible to build a protoc binary for an architecture
-that is different from what Java has detected, as long as you have the proper
-compilers installed.
+To run the image:
+
+```
+$ docker run -it --rm=true protoc-artifacts bash
+```
 
 
-You can override the Maven properties ``os.detected.name`` and
-``os.detected.arch`` to force the script to generate binaries for a specific OS
-and/or architecture. Valid values are defined as the return values of
-``normalizeOs()`` and ``normalizeArch()`` of ``Detector`` from
-[os-maven-plugin](https://github.com/trustin/os-maven-plugin/blob/master/src/main/java/kr/motd/maven/os/Detector.java).
-Frequently used values are:
-- ``os.detected.name``: ``linux``, ``osx``, ``windows``.
-- ``os.detected.arch``: ``x86_32``, ``x86_64``, ``ppcle_64``
+To checkout protobuf (run within the container):
 
 
-For example, MinGW32 only ships with 32-bit compilers, but you can still build
-32-bit protoc under 64-bit Windows, with the following command:
 ```
 ```
-$ mvn install -Dos.detected.arch=x86_32
+$ # Replace v3.5.1 with the version you want
+$ wget -O - https://github.com/google/protobuf/archive/v3.5.1.tar.gz | tar xvzp
 ```
 ```
 
 
+### Windows build
+We no longer use scripts in this directory to build windows artifacts. Instead,
+we use Visual Studio 2015 to build our windows release artifacts. See our
+[kokoro windows build scripts here](../kokoro/release/protoc/windows/build.bat).
+
+To upload windows artifacts, copy the built binaries into this directory and
+put it into the target/windows/(x86_64|x86_32) directory the same way as the
+artifacts for other platforms. That will allow the maven script to find and
+upload the artifacts to maven.
+
 ## To push artifacts to Maven Central
 ## To push artifacts to Maven Central
 Before you can upload artifacts to Maven Central repository, make sure you have
 Before you can upload artifacts to Maven Central repository, make sure you have
 read [this page](http://central.sonatype.org/pages/apache-maven.html) on how to
 read [this page](http://central.sonatype.org/pages/apache-maven.html) on how to
 configure GPG and Sonatype account.
 configure GPG and Sonatype account.
 
 
-You need to perform the deployment for every platform that you want to
-support. DO NOT close the staging repository until you have done the
-deployment for all platforms. Currently the following platforms are supported:
-- Linux (x86_32, x86_64, ppcle_64 and cross compiled aarch_64 or ppcle_64)
-- Windows (x86_32 and x86_64) with
-  - Cygwin64 with MinGW compilers (x86_64)
-  - MSYS with MinGW32 (x86_32)
-  - Cross compile in Linux with MinGW-w64 (x86_32, x86_64)
-- MacOSX (x86_32 and x86_64)
-
-As for MSYS2/MinGW64 for Windows: protoc will build, but it insists on
-adding a dependency of `libwinpthread-1.dll`, which isn't shipped with
-Windows.
+Before you do the deployment, make sure you have built the protoc artifacts for
+every supported platform and put them under the target directory. Example
+target directory layout:
+
+    + pom.xml
+    + target
+      + linux
+        + x86_64
+          protoc.exe
+        + x86_32
+          protoc.exe
+      + macos
+        + x86_64
+          protoc.exe
+        + x86_32
+          protoc.exe
+      + windows
+        + x86_64
+          protoc.exe
+        + x86_32
+          protoc.exe
+
+You will need to build the artifacts on multiple machines and gather them
+together into one place.
 
 
 Use the following command to deploy artifacts for the host platform to a
 Use the following command to deploy artifacts for the host platform to a
 staging repository.
 staging repository.
+
 ```
 ```
 $ mvn clean deploy -P release
 $ mvn clean deploy -P release
 ```
 ```
+
 It creates a new staging repository. Go to
 It creates a new staging repository. Go to
 https://oss.sonatype.org/#stagingRepositories and find the repository, usually
 https://oss.sonatype.org/#stagingRepositories and find the repository, usually
-in the name like ``comgoogle-123``.
-
-You will want to run this command on a different platform. Remember, in
-subsequent deployments you will need to provide the repository name that you
-have found in the first deployment so that all artifacts go to the same
-repository:
-```
-$ mvn clean deploy -P release -Dstaging.repository=comgoogle-123
-```
-
-A 32-bit artifact can be deployed from a 64-bit host with
-``-Dos.detected.arch=x86_32``
-
-An arm64 artifact can be deployed from x86 host with
-``-Dos.detected.arch=aarch_64``
-
-A ppcle_64 artifact can be deployed from x86 host with
-``-Dos.detected.arch=ppcle_64``
-
-A windows artifact can be deployed from a linux machine with
-``-Dos.detected.name=windows``
-
-When you have done deployment for all platforms, go to
-https://oss.sonatype.org/#stagingRepositories, verify that the staging
-repository has all the binaries, close and release this repository.
+in the name like ``comgoogle-123``. Verify that the staging repository has all
+the binaries, close and release this repository.
 
 
 ## Upload zip packages to github release page.
 ## Upload zip packages to github release page.
 After uploading protoc artifacts to Maven Central repository, run the
 After uploading protoc artifacts to Maven Central repository, run the
 build-zip.sh script to bulid zip packages for these protoc binaries
 build-zip.sh script to bulid zip packages for these protoc binaries
 and upload these zip packages to the download section of the github
 and upload these zip packages to the download section of the github
 release. For example:
 release. For example:
+
 ```
 ```
 $ ./build-zip.sh 3.6.0
 $ ./build-zip.sh 3.6.0
 ```
 ```
-The above command will create 6 zip files:
+
+The above command will create 5 zip files:
+
 ```
 ```
 dist/protoc-3.6.0-win32.zip
 dist/protoc-3.6.0-win32.zip
 dist/protoc-3.6.0-osx-x86_32.zip
 dist/protoc-3.6.0-osx-x86_32.zip
@@ -129,70 +165,14 @@ dist/protoc-3.6.0-linux-x86_32.zip
 dist/protoc-3.6.0-linux-x86_64.zip
 dist/protoc-3.6.0-linux-x86_64.zip
 dist/protoc-3.6.0-linux-ppcle_64.zip
 dist/protoc-3.6.0-linux-ppcle_64.zip
 ```
 ```
+
 Before running the script, make sure the artifacts are accessible from:
 Before running the script, make sure the artifacts are accessible from:
 http://repo1.maven.org/maven2/com/google/protobuf/protoc/
 http://repo1.maven.org/maven2/com/google/protobuf/protoc/
 
 
-### Tips for deploying on Linux
-We build on Centos 6.6 to provide a good compatibility for not very new
-systems. We have provided a ``Dockerfile`` under this directory to build the
-environment. It has been tested with Docker 1.6.1.
-
-To build a image:
-```
-$ docker build -t protoc-artifacts .
-```
-
-To run the image:
-```
-$ docker run -it --rm=true protoc-artifacts bash
-```
-
-To checkout protobuf (run within the container):
-```
-$ # Replace v3.5.1 with the version you want
-$ wget -O - https://github.com/google/protobuf/archive/v3.5.1.tar.gz | tar xvzp
-```
-
-### Tips for deploying on Windows
-Under Windows the following error may occur: ``gpg: cannot open tty `no tty':
-No such file or directory``. This can be fixed by configuring gpg through an
-active profile in ``.m2\settings.xml`` where also the Sonatype password is
-stored:
-```xml
-<settings>
-  <servers>
-    <server>
-      <id>sonatype-nexus-staging</id>
-      <username>[username]</username>
-      <password>[password]</password>
-    </server>
-  </servers>
-  <profiles>
-    <profile>
-      <id>gpg</id>
-      <properties>
-        <gpg.executable>gpg</gpg.executable>
-        <gpg.passphrase>[password]</gpg.passphrase>
-      </properties>
-    </profile>
-  </profiles>
-  <activeProfiles>
-    <activeProfile>gpg</activeProfile>
-  </activeProfiles>
-</settings>
-```
-
-### Tested build environments
+## Tested build environments
 We have successfully built artifacts on the following environments:
 We have successfully built artifacts on the following environments:
 - Linux x86_32 and x86_64:
 - Linux x86_32 and x86_64:
-  - Centos 6.6 (within Docker 1.6.1)
-  - Ubuntu 14.04.2 64-bit
-- Linux ppc64le:
-  - Debian 9.4
-  - Cross compiled with `g++-powerpc64le-linux-gnu` on Debian 9.4 x86_64
-- Linux aarch_64: Cross compiled with `g++-aarch64-linux-gnu` on Ubuntu 14.04.2 64-bit
-- Windows x86_32: MSYS with ``mingw32-gcc-g++ 4.8.1-4`` on Windows 7 64-bit
-- Windows x86_32: Cross compile with ``i686-w64-mingw32-g++ 4.8.2`` on Ubuntu 14.04.2 64-bit
-- Windows x86_64: Cygwin64 with ``mingw64-x86_64-gcc-g++ 4.8.3-1`` on Windows 7 64-bit
-- Windows x86_64: Cross compile with ``x86_64-w64-mingw32-g++ 4.8.2`` on Ubuntu 14.04.2 64-bit
+  - Centos 6.9 (within Docker 1.6.1)
+  - Ubuntu 14.04.5 64-bit
+- Linux aarch_64: Cross compiled with `g++-aarch64-linux-gnu` on Ubuntu 14.04.5 64-bit
 - Mac OS X x86_32 and x86_64: Mac OS X 10.9.5
 - Mac OS X x86_32 and x86_64: Mac OS X 10.9.5

+ 37 - 24
protoc-artifacts/build-protoc.sh

@@ -1,24 +1,34 @@
 #!/bin/bash
 #!/bin/bash
 
 
-# Builds protoc executable into target/protoc.exe; optionally build protoc
-# plugins into target/protoc-gen-*.exe
-# To be run from Maven.
-# Usage: build-protoc.sh <OS> <ARCH> <TARGET>
-# <OS> and <ARCH> are ${os.detected.name} and ${os.detected.arch} from os-maven-plugin
-# <TARGET> can be "protoc" or "protoc-gen-javalite"
+# Builds protoc executable into target/<OS>/<ARCH>/protoc.exe; optionally builds
+# protoc plugins into target/<OS>/<ARCH>/protoc-gen-*.exe
 #
 #
-# The script now supports cross-compiling windows, linux-arm64, and linux-ppc64le in linux-x86
-# environment. Required packages:
-# - Windows: i686-w64-mingw32-gcc (32bit) and x86_64-w64-mingw32-gcc (64bit)
-# - Arm64: g++-aarch64-linux-gnu
-# - Ppc64le: g++-powerpc64le-linux-gcc
+# Usage: ./build-protoc.sh <OS> <ARCH> <TARGET>
+#
+# <TARGET> can be "protoc" or "protoc-gen-javalite". Supported <OS> <ARCH>
+# combinations:
+#   HOST   <OS>    <ARCH>   <COMMENT>
+#   cygwin windows x86_32   Requires: i686-w64-mingw32-gcc
+#   cygwin windows x86_64   Requires: x86_64-w64-mingw32-gcc
+#   linux  linux   aarch_64 Requires: g++-aarch64-linux-gnu
+#   linux  linux   x86_32
+#   linux  linux   x86_64
+#   linux  windows x86_32   Requires: i686-w64-mingw32-gcc
+#   linux  windows x86_64   Requires: x86_64-w64-mingw32-gcc
+#   macos  osx     x86_32
+#   macos  osx     x86_64
+#   mingw  windows x86_32
+#   mingw  windows x86_64
+#
+# Before running this script, make sure you have generated the configure script
+# in the parent directory (i.e., run ./autogen.sh there).
 
 
 OS=$1
 OS=$1
 ARCH=$2
 ARCH=$2
 MAKE_TARGET=$3
 MAKE_TARGET=$3
 
 
 if [[ $# < 3 ]]; then
 if [[ $# < 3 ]]; then
-  echo "No arguments provided. This script is intended to be run from Maven."
+  echo "Not enough arguments provided."
   exit 1
   exit 1
 fi
 fi
 
 
@@ -28,7 +38,7 @@ case $MAKE_TARGET in
   protoc)
   protoc)
     ;;
     ;;
   *)
   *)
-    echo "Target ""$TARGET"" invalid."
+    echo "Target ""$MAKE_TARGET"" invalid."
     exit 1
     exit 1
 esac
 esac
 
 
@@ -140,7 +150,7 @@ checkDependencies ()
       white_list="linux-vdso64\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libz\.so\.1\|ld64\.so\.2"
       white_list="linux-vdso64\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libz\.so\.1\|ld64\.so\.2"
     elif [[ "$ARCH" == aarch_64 ]]; then
     elif [[ "$ARCH" == aarch_64 ]]; then
       dump_cmd='objdump -p '"$1"' | grep NEEDED'
       dump_cmd='objdump -p '"$1"' | grep NEEDED'
-      white_list="libpthread\.so\.0\|libc\.so\.6\|ld-linux-aarch64\.so\.1"
+      white_list="libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-aarch64\.so\.1"
     fi
     fi
   elif [[ "$OS" == osx ]]; then
   elif [[ "$OS" == osx ]]; then
     dump_cmd='otool -L '"$1"' | fgrep dylib'
     dump_cmd='otool -L '"$1"' | fgrep dylib'
@@ -164,15 +174,10 @@ checkDependencies ()
 }
 }
 ############################################################################
 ############################################################################
 
 
-echo "Building protoc, OS=$OS ARCH=$ARCH TARGET=$TARGET"
-
-# Nested double quotes are unintuitive, but it works.
-cd "$(dirname "$0")"
+echo "Building protoc, OS=$OS ARCH=$ARCH TARGET=$MAKE_TARGET"
 
 
-WORKING_DIR=$(pwd)
 CONFIGURE_ARGS="--disable-shared"
 CONFIGURE_ARGS="--disable-shared"
 
 
-TARGET_FILE=target/$MAKE_TARGET.exe
 if [[ "$OS" == windows ]]; then
 if [[ "$OS" == windows ]]; then
   MAKE_TARGET="${MAKE_TARGET}.exe"
   MAKE_TARGET="${MAKE_TARGET}.exe"
 fi
 fi
@@ -253,10 +258,18 @@ fi
 
 
 export CXXFLAGS LDFLAGS
 export CXXFLAGS LDFLAGS
 
 
-cd "$WORKING_DIR"/.. && ./configure $CONFIGURE_ARGS &&
-  cd src && make clean && make $MAKE_TARGET &&
-  cd "$WORKING_DIR" && mkdir -p target &&
-  cp ../src/$MAKE_TARGET $TARGET_FILE ||
+# Nested double quotes are unintuitive, but it works.
+cd "$(dirname "$0")"
+
+WORKING_DIR="$(pwd)"
+BUILD_DIR="build/$OS/$ARCH"
+TARGET_FILE="target/$OS/$ARCH/$MAKE_TARGET.exe"
+
+mkdir -p "$BUILD_DIR" && cd "$BUILD_DIR" &&
+  ../../../../configure $CONFIGURE_ARGS &&
+  cd src && make $MAKE_TARGET -j8 &&
+  cd "$WORKING_DIR" && mkdir -p $(dirname $TARGET_FILE) &&
+  cp $BUILD_DIR/src/$MAKE_TARGET $TARGET_FILE ||
   exit 1
   exit 1
 
 
 if [[ "$OS" == osx ]]; then
 if [[ "$OS" == osx ]]; then

+ 32 - 31
protoc-artifacts/pom.xml

@@ -33,36 +33,7 @@
     </connection>
     </connection>
   </scm>
   </scm>
   <build>
   <build>
-    <extensions>
-      <extension>
-        <groupId>kr.motd.maven</groupId>
-        <artifactId>os-maven-plugin</artifactId>
-        <version>1.5.0.Final</version>
-      </extension>
-    </extensions>
     <plugins>
     <plugins>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>exec-maven-plugin</artifactId>
-        <version>1.1.1</version>
-        <executions>
-          <execution>
-            <phase>compile</phase>
-            <goals>
-              <goal>exec</goal>
-            </goals>
-          </execution>
-        </executions>
-        <configuration>
-          <executable>bash</executable>
-          <arguments>
-            <argument>build-protoc.sh</argument>
-            <argument>${os.detected.name}</argument>
-            <argument>${os.detected.arch}</argument>
-            <argument>protoc</argument>
-          </arguments>
-        </configuration>
-      </plugin>
       <plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>build-helper-maven-plugin</artifactId>
         <artifactId>build-helper-maven-plugin</artifactId>
@@ -77,8 +48,38 @@
             <configuration>
             <configuration>
               <artifacts>
               <artifacts>
                 <artifact>
                 <artifact>
-                  <file>${basedir}/target/protoc.exe</file>
-                  <classifier>${os.detected.name}-${os.detected.arch}</classifier>
+                  <file>${basedir}/target/linux/x86_64/protoc.exe</file>
+                  <classifier>linux-x86_64</classifier>
+                  <type>exe</type>
+                </artifact>
+                <artifact>
+                  <file>${basedir}/target/linux/x86_32/protoc.exe</file>
+                  <classifier>linux-x86_32</classifier>
+                  <type>exe</type>
+                </artifact>
+                <artifact>
+                  <file>${basedir}/target/windows/x86_64/protoc.exe</file>
+                  <classifier>windows-x86_64</classifier>
+                  <type>exe</type>
+                </artifact>
+                <artifact>
+                  <file>${basedir}/target/windows/x86_32/protoc.exe</file>
+                  <classifier>windows-x86_32</classifier>
+                  <type>exe</type>
+                </artifact>
+                <artifact>
+                  <file>${basedir}/target/osx/x86_64/protoc.exe</file>
+                  <classifier>osx-x86_64</classifier>
+                  <type>exe</type>
+                </artifact>
+                <artifact>
+                  <file>${basedir}/target/osx/x86_32/protoc.exe</file>
+                  <classifier>osx-x86_32</classifier>
+                  <type>exe</type>
+                </artifact>
+                <artifact>
+                  <file>${basedir}/target/linux/aarch_64/protoc.exe</file>
+                  <classifier>linux-aarch_64</classifier>
                   <type>exe</type>
                   <type>exe</type>
                 </artifact>
                 </artifact>
               </artifacts>
               </artifacts>

+ 1 - 1
protoc-artifacts/scl-enable-devtoolset.sh

@@ -10,4 +10,4 @@ quote() {
   done
   done
 }
 }
 
 
-exec scl enable devtoolset-1.1 "$(quote "$@")"
+exec scl enable devtoolset-2 "$(quote "$@")"

+ 2 - 1
python/tox.ini

@@ -4,7 +4,8 @@ envlist =
 
 
 [testenv]
 [testenv]
 usedevelop=true
 usedevelop=true
-passenv = CC
+passenv = 
+    CC KOKORO_BUILD_ID KOKORO_BUILD_NUMBER
 setenv =
 setenv =
     cpp: LD_LIBRARY_PATH={toxinidir}/../src/.libs
     cpp: LD_LIBRARY_PATH={toxinidir}/../src/.libs
     cpp: DYLD_LIBRARY_PATH={toxinidir}/../src/.libs
     cpp: DYLD_LIBRARY_PATH={toxinidir}/../src/.libs

+ 128 - 31
ruby/compatibility_tests/v3.0.0/tests/basic.rb

@@ -222,33 +222,55 @@ module BasicTest
 
 
     def test_type_errors
     def test_type_errors
       m = TestMessage.new
       m = TestMessage.new
-      assert_raise TypeError do
+
+      # Use rescue to allow subclasses of error
+      success = false
+      begin
         m.optional_int32 = "hello"
         m.optional_int32 = "hello"
+      rescue TypeError
+        success = true
       end
       end
-      assert_raise TypeError do
-        m.optional_string = 42
-      end
-      assert_raise TypeError do
+      assert(success)
+
+      success = false
+      begin
         m.optional_string = nil
         m.optional_string = nil
+      rescue TypeError
+        success = true
       end
       end
-      assert_raise TypeError do
+      assert(success)
+
+      success = false
+      begin
         m.optional_bool = 42
         m.optional_bool = 42
+      rescue TypeError
+        success = true
       end
       end
-      assert_raise TypeError do
+      assert(success)
+
+      success = false
+      begin
         m.optional_msg = TestMessage.new  # expects TestMessage2
         m.optional_msg = TestMessage.new  # expects TestMessage2
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
-      assert_raise TypeError do
+      success = false
+      begin
         m.repeated_int32 = []  # needs RepeatedField
         m.repeated_int32 = []  # needs RepeatedField
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
-      assert_raise TypeError do
-        m.repeated_int32.push "hello"
-      end
-
-      assert_raise TypeError do
+      success = false
+      begin
         m.repeated_msg.push TestMessage.new
         m.repeated_msg.push TestMessage.new
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
     end
     end
 
 
     def test_string_encoding
     def test_string_encoding
@@ -275,7 +297,7 @@ module BasicTest
 
 
       # strings are immutable so we can't do this, but serialize should catch it.
       # strings are immutable so we can't do this, but serialize should catch it.
       m.optional_string = "asdf".encode!('UTF-8')
       m.optional_string = "asdf".encode!('UTF-8')
-      assert_raise RuntimeError do
+      assert_raise do
         m.optional_string.encode!('ASCII-8BIT')
         m.optional_string.encode!('ASCII-8BIT')
       end
       end
     end
     end
@@ -312,10 +334,14 @@ module BasicTest
       assert l.pop == 9
       assert l.pop == 9
       assert l == [5, 2, 3, 4, 7, 8]
       assert l == [5, 2, 3, 4, 7, 8]
 
 
-      assert_raise TypeError do
+      success = false
+      begin
         m = TestMessage.new
         m = TestMessage.new
         l.push m
         l.push m
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
       m = TestMessage.new
       m = TestMessage.new
       m.repeated_int32 = l
       m.repeated_int32 = l
@@ -362,12 +388,22 @@ module BasicTest
       l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
       l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
       l.push TestMessage.new
       l.push TestMessage.new
       assert l.count == 1
       assert l.count == 1
-      assert_raise TypeError do
+
+      success = false
+      begin
         l.push TestMessage2.new
         l.push TestMessage2.new
+      rescue TypeError
+        success = true
       end
       end
-      assert_raise TypeError do
+      assert(success)
+
+      success = false
+      begin
         l.push 42
         l.push 42
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
       l2 = l.dup
       l2 = l.dup
       assert l2[0] == l[0]
       assert l2[0] == l[0]
@@ -493,9 +529,14 @@ module BasicTest
       assert m.length == 0
       assert m.length == 0
       assert m == {}
       assert m == {}
 
 
-      assert_raise TypeError do
+      success = false
+      begin
         m[1] = 1
         m[1] = 1
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
+
       assert_raise RangeError do
       assert_raise RangeError do
         m["asdf"] = 0x1_0000_0000
         m["asdf"] = 0x1_0000_0000
       end
       end
@@ -514,18 +555,28 @@ module BasicTest
       assert_raise RangeError do
       assert_raise RangeError do
         m[0x8000_0000] = 1
         m[0x8000_0000] = 1
       end
       end
-      assert_raise TypeError do
+
+      success = false
+      begin
         m["asdf"] = 1
         m["asdf"] = 1
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
       m = Google::Protobuf::Map.new(:int64, :int32)
       m = Google::Protobuf::Map.new(:int64, :int32)
       m[0x1000_0000_0000_0000] = 1
       m[0x1000_0000_0000_0000] = 1
       assert_raise RangeError do
       assert_raise RangeError do
         m[0x1_0000_0000_0000_0000] = 1
         m[0x1_0000_0000_0000_0000] = 1
       end
       end
-      assert_raise TypeError do
+
+      success = false
+      begin
         m["asdf"] = 1
         m["asdf"] = 1
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
       m = Google::Protobuf::Map.new(:uint32, :int32)
       m = Google::Protobuf::Map.new(:uint32, :int32)
       m[0x8000_0000] = 1
       m[0x8000_0000] = 1
@@ -548,18 +599,32 @@ module BasicTest
       m = Google::Protobuf::Map.new(:bool, :int32)
       m = Google::Protobuf::Map.new(:bool, :int32)
       m[true] = 1
       m[true] = 1
       m[false] = 2
       m[false] = 2
-      assert_raise TypeError do
+
+      success = false
+      begin
         m[1] = 1
         m[1] = 1
+      rescue TypeError
+        success = true
       end
       end
-      assert_raise TypeError do
+      assert(success)
+
+      success = false
+      begin
         m["asdf"] = 1
         m["asdf"] = 1
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
       m = Google::Protobuf::Map.new(:string, :int32)
       m = Google::Protobuf::Map.new(:string, :int32)
       m["asdf"] = 1
       m["asdf"] = 1
-      assert_raise TypeError do
+      success = false
+      begin
         m[1] = 1
         m[1] = 1
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
       assert_raise Encoding::UndefinedConversionError do
       assert_raise Encoding::UndefinedConversionError do
         bytestring = ["FFFF"].pack("H*")
         bytestring = ["FFFF"].pack("H*")
         m[bytestring] = 1
         m[bytestring] = 1
@@ -570,17 +635,25 @@ module BasicTest
       m[bytestring] = 1
       m[bytestring] = 1
       # Allowed -- we will automatically convert to ASCII-8BIT.
       # Allowed -- we will automatically convert to ASCII-8BIT.
       m["asdf"] = 1
       m["asdf"] = 1
-      assert_raise TypeError do
+      success = false
+      begin
         m[1] = 1
         m[1] = 1
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
     end
     end
 
 
     def test_map_msg_enum_valuetypes
     def test_map_msg_enum_valuetypes
       m = Google::Protobuf::Map.new(:string, :message, TestMessage)
       m = Google::Protobuf::Map.new(:string, :message, TestMessage)
       m["asdf"] = TestMessage.new
       m["asdf"] = TestMessage.new
-      assert_raise TypeError do
+      success = false
+      begin
         m["jkl;"] = TestMessage2.new
         m["jkl;"] = TestMessage2.new
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
       m = Google::Protobuf::Map.new(
       m = Google::Protobuf::Map.new(
         :string, :message, TestMessage,
         :string, :message, TestMessage,
@@ -645,23 +718,39 @@ module BasicTest
       m.map_string_msg.delete("c")
       m.map_string_msg.delete("c")
       assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
       assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
 
 
-      assert_raise TypeError do
+      success = false
+      begin
         m.map_string_msg["e"] = TestMessage.new # wrong value type
         m.map_string_msg["e"] = TestMessage.new # wrong value type
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
       # ensure nothing was added by the above
       # ensure nothing was added by the above
       assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
       assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
 
 
       m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
       m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
-      assert_raise TypeError do
+      success = false
+      begin
         m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
         m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
+      rescue TypeError
+        success = true
       end
       end
-      assert_raise TypeError do
+      assert(success)
+      success = false
+      begin
         m.map_string_int32 = {}
         m.map_string_int32 = {}
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
 
 
-      assert_raise TypeError do
+      success = false
+      begin
         m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
         m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
     end
     end
 
 
     def test_map_encode_decode
     def test_map_encode_decode
@@ -922,22 +1011,30 @@ module BasicTest
 
 
     def test_def_errors
     def test_def_errors
       s = Google::Protobuf::DescriptorPool.new
       s = Google::Protobuf::DescriptorPool.new
-      assert_raise TypeError do
+      success = false
+      begin
         s.build do
         s.build do
           # enum with no default (integer value 0)
           # enum with no default (integer value 0)
           add_enum "MyEnum" do
           add_enum "MyEnum" do
             value :A, 1
             value :A, 1
           end
           end
         end
         end
+      rescue TypeError
+        success = true
       end
       end
-      assert_raise TypeError do
+      assert(success)
+      success = false
+      begin
         s.build do
         s.build do
           # message with required field (unsupported in proto3)
           # message with required field (unsupported in proto3)
           add_message "MyMessage" do
           add_message "MyMessage" do
             required :foo, :int32, 1
             required :foo, :int32, 1
           end
           end
         end
         end
+      rescue TypeError
+        success = true
       end
       end
+      assert(success)
     end
     end
 
 
     def test_corecursive
     def test_corecursive

+ 1 - 1
ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb

@@ -18,7 +18,7 @@ class RepeatedFieldTest < Test::Unit::TestCase
     # jRuby additions to the Array class that we can ignore
     # jRuby additions to the Array class that we can ignore
     arr_methods -= [ :indices, :iter_for_each, :iter_for_each_index,
     arr_methods -= [ :indices, :iter_for_each, :iter_for_each_index,
       :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple,
       :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple,
-      :nitems, :iter_for_reverse_each, :indexes]
+      :nitems, :iter_for_reverse_each, :indexes, :append, :prepend]
     arr_methods.each do |method_name|
     arr_methods.each do |method_name|
       assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"
       assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"
     end
     end

+ 2 - 2
ruby/ext/google/protobuf_c/storage.c

@@ -177,7 +177,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
     }
     }
     case UPB_TYPE_STRING:
     case UPB_TYPE_STRING:
       if (CLASS_OF(value) == rb_cSymbol) {
       if (CLASS_OF(value) == rb_cSymbol) {
-        value = rb_funcall(value, rb_intern("to_s"), 0, NULL);
+        value = rb_funcall(value, rb_intern("to_s"), 0);
       } else if (CLASS_OF(value) != rb_cString) {
       } else if (CLASS_OF(value) != rb_cString) {
         rb_raise(rb_eTypeError, "Invalid argument for string field.");
         rb_raise(rb_eTypeError, "Invalid argument for string field.");
       }
       }
@@ -207,7 +207,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
     case UPB_TYPE_ENUM: {
     case UPB_TYPE_ENUM: {
       int32_t int_val = 0;
       int32_t int_val = 0;
       if (TYPE(value) == T_STRING) {
       if (TYPE(value) == T_STRING) {
-        value = rb_funcall(value, rb_intern("to_sym"), 0, NULL);
+        value = rb_funcall(value, rb_intern("to_sym"), 0);
       } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
       } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
         rb_raise(rb_eTypeError,
         rb_raise(rb_eTypeError,
                  "Expected number or symbol type for enum field.");
                  "Expected number or symbol type for enum field.");

+ 3 - 1
ruby/tests/basic.rb

@@ -336,7 +336,9 @@ module BasicTest
 
 
       # strings are immutable so we can't do this, but serialize should catch it.
       # strings are immutable so we can't do this, but serialize should catch it.
       m.optional_string = "asdf".encode!('UTF-8')
       m.optional_string = "asdf".encode!('UTF-8')
-      assert_raise RuntimeError do
+      # Ruby 2.5 changed to raise FrozenError. However, assert_raise don't
+      # accept subclass. Don't specify type here.
+      assert_raise do
         m.optional_string.encode!('ASCII-8BIT')
         m.optional_string.encode!('ASCII-8BIT')
       end
       end
     end
     end

+ 1 - 1
ruby/tests/repeated_field_test.rb

@@ -18,7 +18,7 @@ class RepeatedFieldTest < Test::Unit::TestCase
     # jRuby additions to the Array class that we can ignore
     # jRuby additions to the Array class that we can ignore
     arr_methods -= [ :indices, :iter_for_each, :iter_for_each_index,
     arr_methods -= [ :indices, :iter_for_each, :iter_for_each_index,
       :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple,
       :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple,
-      :nitems, :iter_for_reverse_each, :indexes]
+      :nitems, :iter_for_reverse_each, :indexes, :append, :prepend]
     arr_methods.each do |method_name|
     arr_methods.each do |method_name|
       assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"
       assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"
     end
     end

+ 1 - 20
src/Makefile.am

@@ -56,9 +56,7 @@ clean-local:
 
 
 CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
 CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
              testzip.jar testzip.list testzip.proto testzip.zip \
              testzip.jar testzip.list testzip.proto testzip.zip \
-             no_warning_test.cc \
-             google/protobuf/compiler/js/well_known_types_embed.cc \
-             js_embed$(EXEEXT)
+             no_warning_test.cc
 
 
 MAINTAINERCLEANFILES =   \
 MAINTAINERCLEANFILES =   \
   Makefile.in
   Makefile.in
@@ -471,22 +469,6 @@ bin_PROGRAMS = protoc
 protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
 protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
 protoc_SOURCES = google/protobuf/compiler/main.cc
 protoc_SOURCES = google/protobuf/compiler/main.cc
 
 
-# The special JS code for the well-known types is linked into the compiler via
-# well_known_types_embed.cc, which is generated from .js source files. We have
-# to build the js_embed binary using $(CXX_FOR_BUILD) so that it is executable
-# on the build machine in a cross-compilation setup.
-js_embed$(EXEEXT): $(srcdir)/google/protobuf/compiler/js/embed.cc
-	$(CXX_FOR_BUILD) -o $@ $<
-js_well_known_types_sources =                                  \
-	google/protobuf/compiler/js/well_known_types/any.js          \
-	google/protobuf/compiler/js/well_known_types/struct.js       \
-	google/protobuf/compiler/js/well_known_types/timestamp.js
-# We have to cd to $(srcdir) so that out-of-tree builds work properly.
-google/protobuf/compiler/js/well_known_types_embed.cc: js_embed$(EXEEXT) $(js_well_known_types_sources)
-	mkdir -p `dirname $@` && \
-	oldpwd=`pwd` && cd $(srcdir) && \
-	$$oldpwd/js_embed$(EXEEXT) $(js_well_known_types_sources) > $$oldpwd/$@
-
 # Tests ==============================================================
 # Tests ==============================================================
 
 
 protoc_inputs =                                                   \
 protoc_inputs =                                                   \
@@ -565,7 +547,6 @@ EXTRA_DIST =                                                   \
   google/protobuf/package_info.h                               \
   google/protobuf/package_info.h                               \
   google/protobuf/io/package_info.h                            \
   google/protobuf/io/package_info.h                            \
   google/protobuf/util/package_info.h                          \
   google/protobuf/util/package_info.h                          \
-  google/protobuf/compiler/js/embed.cc                         \
   google/protobuf/compiler/ruby/ruby_generated_code.proto      \
   google/protobuf/compiler/ruby/ruby_generated_code.proto      \
   google/protobuf/compiler/ruby/ruby_generated_code_pb.rb      \
   google/protobuf/compiler/ruby/ruby_generated_code_pb.rb      \
   google/protobuf/compiler/package_info.h                      \
   google/protobuf/compiler/package_info.h                      \

+ 0 - 110
src/google/protobuf/compiler/js/embed.cc

@@ -1,110 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must 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 <cassert>
-#include <cstdlib>
-#include <fstream>
-#include <iostream>
-#include <string>
-
-static bool AsciiIsPrint(unsigned char c) {
-  return c >= 32 && c < 127;
-}
-
-static char ToDecimalDigit(int num) {
-  assert(num < 10);
-  return '0' + num;
-}
-
-static std::string CEscape(const std::string& str) {
-  std::string dest;
-
-  for (size_t i = 0; i < str.size(); ++i) {
-    unsigned char ch = str[i];
-    switch (ch) {
-      case '\n': dest += "\\n"; break;
-      case '\r': dest += "\\r"; break;
-      case '\t': dest += "\\t"; break;
-      case '\"': dest += "\\\""; break;
-      case '\\': dest += "\\\\"; break;
-      default:
-        if (AsciiIsPrint(ch)) {
-          dest += ch;
-        } else {
-          dest += "\\";
-          dest += ToDecimalDigit(ch / 64);
-          dest += ToDecimalDigit((ch % 64) / 8);
-          dest += ToDecimalDigit(ch % 8);
-        }
-        break;
-    }
-  }
-
-  return dest;
-}
-
-static void AddFile(const char* name, std::basic_ostream<char>* out) {
-  std::ifstream in(name);
-
-  if (!in.is_open()) {
-    std::cerr << "Couldn't open input file: " << name << "\n";
-    std::exit(EXIT_FAILURE);
-  }
-
-  // Make canonical name only include the final element.
-  for (const char *p = name; *p; p++) {
-    if (*p == '/') {
-      name = p + 1;
-    }
-  }
-
-  *out << "{\"" << CEscape(name) << "\",\n";
-
-  for (std::string line; std::getline(in, line); ) {
-    *out << "  \"" << CEscape(line) << "\\n\"\n";
-  }
-
-  *out << "},\n";
-}
-
-int main(int argc, char *argv[]) {
-  std::cout << "#include "
-               "\"google/protobuf/compiler/js/well_known_types_embed.h\"\n";
-  std::cout << "struct FileToc well_known_types_js[] = {\n";
-
-  for (int i = 1; i < argc; i++) {
-    AddFile(argv[i], &std::cout);
-  }
-
-  std::cout << "  {NULL, NULL}  // Terminate the list.\n";
-  std::cout << "};\n";
-
-  return EXIT_SUCCESS;
-}

+ 225 - 0
src/google/protobuf/compiler/js/well_known_types_embed.cc

@@ -0,0 +1,225 @@
+#include <google/protobuf/compiler/js/well_known_types_embed.h>
+
+struct FileToc well_known_types_js[] = {
+    {"any.js",
+     "/* This code will be inserted into generated code for\n"
+     " * google/protobuf/any.proto. */\n"
+     "\n"
+     "/**\n"
+     " * Returns the type name contained in this instance, if any.\n"
+     " * @return {string|undefined}\n"
+     " */\n"
+     "proto.google.protobuf.Any.prototype.getTypeName = function() {\n"
+     "  return this.getTypeUrl().split('/').pop();\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Packs the given message instance into this Any.\n"
+     " * @param {!Uint8Array} serialized The serialized data to pack.\n"
+     " * @param {string} name The type name of this message object.\n"
+     " * @param {string=} opt_typeUrlPrefix the type URL prefix.\n"
+     " */\n"
+     "proto.google.protobuf.Any.prototype.pack = function(serialized, name,\n"
+     "                                                    opt_typeUrlPrefix) "
+     "{\n"
+     "  if (!opt_typeUrlPrefix) {\n"
+     "    opt_typeUrlPrefix = 'type.googleapis.com/';\n"
+     "  }\n"
+     "\n"
+     "  if (opt_typeUrlPrefix.substr(-1) != '/') {\n"
+     "    this.setTypeUrl(opt_typeUrlPrefix + '/' + name);\n"
+     "  } else {\n"
+     "    this.setTypeUrl(opt_typeUrlPrefix + name);\n"
+     "  }\n"
+     "\n"
+     "  this.setValue(serialized);\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * @template T\n"
+     " * Unpacks this Any into the given message object.\n"
+     " * @param {function(Uint8Array):T} deserialize Function that will "
+     "deserialize\n"
+     " *     the binary data properly.\n"
+     " * @param {string} name The expected type name of this message object.\n"
+     " * @return {?T} If the name matched the expected name, returns the "
+     "deserialized\n"
+     " *     object, otherwise returns null.\n"
+     " */\n"
+     "proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) "
+     "{\n"
+     "  if (this.getTypeName() == name) {\n"
+     "    return deserialize(this.getValue_asU8());\n"
+     "  } else {\n"
+     "    return null;\n"
+     "  }\n"
+     "};\n"},
+    {"timestamp.js",
+     "/* This code will be inserted into generated code for\n"
+     " * google/protobuf/timestamp.proto. */\n"
+     "\n"
+     "/**\n"
+     " * Returns a JavaScript 'Date' object corresponding to this Timestamp.\n"
+     " * @return {!Date}\n"
+     " */\n"
+     "proto.google.protobuf.Timestamp.prototype.toDate = function() {\n"
+     "  var seconds = this.getSeconds();\n"
+     "  var nanos = this.getNanos();\n"
+     "\n"
+     "  return new Date((seconds * 1000) + (nanos / 1000000));\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Sets the value of this Timestamp object to be the given Date.\n"
+     " * @param {!Date} value The value to set.\n"
+     " */\n"
+     "proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {\n"
+     "  this.setSeconds(Math.floor(value.getTime() / 1000));\n"
+     "  this.setNanos(value.getMilliseconds() * 1000000);\n"
+     "};\n"},
+    {"struct.js",
+     "/* This code will be inserted into generated code for\n"
+     " * google/protobuf/struct.proto. */\n"
+     "\n"
+     "/**\n"
+     " * Typedef representing plain JavaScript values that can go into a\n"
+     " *     Struct.\n"
+     " * @typedef {null|number|string|boolean|Array|Object}\n"
+     " */\n"
+     "proto.google.protobuf.JavaScriptValue;\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Converts this Value object to a plain JavaScript value.\n"
+     " * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript\n"
+     " *     value representing this Struct.\n"
+     " */\n"
+     "proto.google.protobuf.Value.prototype.toJavaScript = function() {\n"
+     "  var kindCase = proto.google.protobuf.Value.KindCase;\n"
+     "  switch (this.getKindCase()) {\n"
+     "    case kindCase.NULL_VALUE:\n"
+     "      return null;\n"
+     "    case kindCase.NUMBER_VALUE:\n"
+     "      return this.getNumberValue();\n"
+     "    case kindCase.STRING_VALUE:\n"
+     "      return this.getStringValue();\n"
+     "    case kindCase.BOOL_VALUE:\n"
+     "      return this.getBoolValue();\n"
+     "    case kindCase.STRUCT_VALUE:\n"
+     "      return this.getStructValue().toJavaScript();\n"
+     "    case kindCase.LIST_VALUE:\n"
+     "      return this.getListValue().toJavaScript();\n"
+     "    default:\n"
+     "      throw new Error('Unexpected struct type');\n"
+     "  }\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Converts this JavaScript value to a new Value proto.\n"
+     " * @param {!proto.google.protobuf.JavaScriptValue} value The value to\n"
+     " *     convert.\n"
+     " * @return {!proto.google.protobuf.Value} The newly constructed value.\n"
+     " */\n"
+     "proto.google.protobuf.Value.fromJavaScript = function(value) {\n"
+     "  var ret = new proto.google.protobuf.Value();\n"
+     "  switch (goog.typeOf(value)) {\n"
+     "    case 'string':\n"
+     "      ret.setStringValue(/** @type {string} */ (value));\n"
+     "      break;\n"
+     "    case 'number':\n"
+     "      ret.setNumberValue(/** @type {number} */ (value));\n"
+     "      break;\n"
+     "    case 'boolean':\n"
+     "      ret.setBoolValue(/** @type {boolean} */ (value));\n"
+     "      break;\n"
+     "    case 'null':\n"
+     "      ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE);\n"
+     "      break;\n"
+     "    case 'array':\n"
+     "      ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript(\n"
+     "          /** @type{!Array} */ (value)));\n"
+     "      break;\n"
+     "    case 'object':\n"
+     "      ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript(\n"
+     "          /** @type{!Object} */ (value)));\n"
+     "      break;\n"
+     "    default:\n"
+     "      throw new Error('Unexpected struct type.');\n"
+     "  }\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Converts this ListValue object to a plain JavaScript array.\n"
+     " * @return {!Array} a plain JavaScript array representing this List.\n"
+     " */\n"
+     "proto.google.protobuf.ListValue.prototype.toJavaScript = function() {\n"
+     "  var ret = [];\n"
+     "  var values = this.getValuesList();\n"
+     "\n"
+     "  for (var i = 0; i < values.length; i++) {\n"
+     "    ret[i] = values[i].toJavaScript();\n"
+     "  }\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Constructs a ListValue protobuf from this plain JavaScript array.\n"
+     " * @param {!Array} array a plain JavaScript array\n"
+     " * @return {proto.google.protobuf.ListValue} a new ListValue object\n"
+     " */\n"
+     "proto.google.protobuf.ListValue.fromJavaScript = function(array) {\n"
+     "  var ret = new proto.google.protobuf.ListValue();\n"
+     "\n"
+     "  for (var i = 0; i < array.length; i++) {\n"
+     "    "
+     "ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i]));\n"
+     "  }\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Converts this Struct object to a plain JavaScript object.\n"
+     " * @return {!Object<string, !proto.google.protobuf.JavaScriptValue>} a "
+     "plain\n"
+     " *     JavaScript object representing this Struct.\n"
+     " */\n"
+     "proto.google.protobuf.Struct.prototype.toJavaScript = function() {\n"
+     "  var ret = {};\n"
+     "\n"
+     "  this.getFieldsMap().forEach(function(value, key) {\n"
+     "    ret[key] = value.toJavaScript();\n"
+     "  });\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"
+     "\n"
+     "\n"
+     "/**\n"
+     " * Constructs a Struct protobuf from this plain JavaScript object.\n"
+     " * @param {!Object} obj a plain JavaScript object\n"
+     " * @return {proto.google.protobuf.Struct} a new Struct object\n"
+     " */\n"
+     "proto.google.protobuf.Struct.fromJavaScript = function(obj) {\n"
+     "  var ret = new proto.google.protobuf.Struct();\n"
+     "  var map = ret.getFieldsMap();\n"
+     "\n"
+     "  for (var property in obj) {\n"
+     "    var val = obj[property];\n"
+     "    map.set(property, proto.google.protobuf.Value.fromJavaScript(val));\n"
+     "  }\n"
+     "\n"
+     "  return ret;\n"
+     "};\n"},
+    {NULL, NULL}  // Terminate the list.
+};

+ 19 - 95
tests.sh

@@ -1,14 +1,8 @@
 #!/bin/bash
 #!/bin/bash
 #
 #
-# Build and runs tests for the protobuf project.  The tests as written here are
-# used by both Jenkins and Travis, though some specialized logic is required to
-# handle the differences between them.
-
-on_travis() {
-  if [ "$TRAVIS" == "true" ]; then
-    "$@"
-  fi
-}
+# Build and runs tests for the protobuf project. We use this script to run
+# tests on kokoro (Ubuntu and MacOS). It can run locally as well but you
+# will need to make sure the required compilers/tools are available.
 
 
 # For when some other test needs the C++ main build, including protoc and
 # For when some other test needs the C++ main build, including protoc and
 # libprotobuf.
 # libprotobuf.
@@ -18,15 +12,6 @@ internal_build_cpp() {
     return
     return
   fi
   fi
 
 
-  if [[ $(uname -s) == "Linux" && "$TRAVIS" == "true" ]]; then
-    # Install GCC 4.8 to replace the default GCC 4.6. We need 4.8 for more
-    # decent C++ 11 support in order to compile conformance tests.
-    sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
-    sudo apt-get update -qq
-    sudo apt-get install -qq g++-4.8
-    export CXX="g++-4.8" CC="gcc-4.8"
-  fi
-
   # Initialize any submodules.
   # Initialize any submodules.
   git submodule update --init --recursive
   git submodule update --init --recursive
 
 
@@ -43,8 +28,6 @@ build_cpp() {
 
 
   # The benchmark code depends on cmake, so test if it is installed before
   # The benchmark code depends on cmake, so test if it is installed before
   # trying to do the build.
   # trying to do the build.
-  # NOTE: The travis macOS images say they have cmake, but the xcode8.1 image
-  # appears to be missing it: https://github.com/travis-ci/travis-ci/issues/6996
   if [[ $(type cmake 2>/dev/null) ]]; then
   if [[ $(type cmake 2>/dev/null) ]]; then
     # Verify benchmarking code can build successfully.
     # Verify benchmarking code can build successfully.
     cd benchmarks && make cpp-benchmark && cd ..
     cd benchmarks && make cpp-benchmark && cd ..
@@ -121,10 +104,6 @@ build_golang() {
   # Add protoc to the path so that the examples build finds it.
   # Add protoc to the path so that the examples build finds it.
   export PATH="`pwd`/src:$PATH"
   export PATH="`pwd`/src:$PATH"
 
 
-  # Install Go and the Go protobuf compiler plugin.
-  on_travis sudo apt-get update -qq
-  on_travis sudo apt-get install -qq golang
-
   export GOPATH="$HOME/gocode"
   export GOPATH="$HOME/gocode"
   mkdir -p "$GOPATH/src/github.com/google"
   mkdir -p "$GOPATH/src/github.com/google"
   rm -f "$GOPATH/src/github.com/google/protobuf"
   rm -f "$GOPATH/src/github.com/google/protobuf"
@@ -139,27 +118,17 @@ use_java() {
   version=$1
   version=$1
   case "$version" in
   case "$version" in
     jdk7)
     jdk7)
-      on_travis sudo apt-get install openjdk-7-jdk
       export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH
       export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH
       export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
       export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
       ;;
       ;;
     oracle7)
     oracle7)
-      if [ "$TRAVIS" == "true" ]; then
-        sudo apt-get install python-software-properties # for apt-add-repository
-        echo "oracle-java7-installer shared/accepted-oracle-license-v1-1 select true" | \
-          sudo debconf-set-selections
-        yes | sudo apt-add-repository ppa:webupd8team/java
-        yes | sudo apt-get install oracle-java7-installer
-      fi;
       export PATH=/usr/lib/jvm/java-7-oracle/bin:$PATH
       export PATH=/usr/lib/jvm/java-7-oracle/bin:$PATH
       export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
       export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
       ;;
       ;;
   esac
   esac
 
 
-  if [ "$TRAVIS" != "true" ]; then
-    MAVEN_LOCAL_REPOSITORY=/var/maven_local_repository
-    MVN="$MVN -e -X --offline -Dmaven.repo.local=$MAVEN_LOCAL_REPOSITORY"
-  fi;
+  MAVEN_LOCAL_REPOSITORY=/var/maven_local_repository
+  MVN="$MVN -e -X --offline -Dmaven.repo.local=$MAVEN_LOCAL_REPOSITORY"
 
 
   which java
   which java
   java -version
   java -version
@@ -190,12 +159,6 @@ build_java_with_conformance_tests() {
   cd conformance && make test_java && cd ..
   cd conformance && make test_java && cd ..
 }
 }
 
 
-build_javanano() {
-  # Java build needs `protoc`.
-  internal_build_cpp
-  cd javanano && $MVN test && cd ..
-}
-
 build_java_jdk7() {
 build_java_jdk7() {
   use_java jdk7
   use_java jdk7
   build_java_with_conformance_tests
   build_java_with_conformance_tests
@@ -213,38 +176,6 @@ build_java_compatibility() {
   ./test.sh 3.0.0-beta-4
   ./test.sh 3.0.0-beta-4
 }
 }
 
 
-build_javanano_jdk7() {
-  use_java jdk7
-  build_javanano
-}
-build_javanano_oracle7() {
-  use_java oracle7
-  build_javanano
-}
-
-internal_install_python_deps() {
-  if [ "$TRAVIS" != "true" ]; then
-    return;
-  fi
-  # Install tox (OS X doesn't have pip).
-  if [ $(uname -s) == "Darwin" ]; then
-    brew upgrade python
-    python3 -m pip install tox
-  else
-    sudo pip install tox
-  fi
-  # Only install Python2.6/3.x on Linux.
-  if [ $(uname -s) == "Linux" ]; then
-    sudo apt-get install -y python-software-properties # for apt-add-repository
-    sudo apt-add-repository -y ppa:fkrull/deadsnakes
-    sudo apt-get update -qq
-    sudo apt-get install -y python3.3 python3.3-dev
-    sudo apt-get install -y python3.4 python3.4-dev
-    sudo apt-get install -y python3.5 python3.5-dev
-    sudo apt-get install -y python3.6 python3.6-dev
-  fi
-}
-
 build_objectivec_ios() {
 build_objectivec_ios() {
   # Reused the build script that takes care of configuring and ensuring things
   # Reused the build script that takes care of configuring and ensuring things
   # are up to date.  The OS X test runs the objc conformance test, so skip it
   # are up to date.  The OS X test runs the objc conformance test, so skip it
@@ -279,9 +210,7 @@ build_objectivec_cocoapods_integration() {
 
 
 build_python() {
 build_python() {
   internal_build_cpp
   internal_build_cpp
-  internal_install_python_deps
   cd python
   cd python
-  # Only test Python 2.6/3.x on Linux
   if [ $(uname -s) == "Linux" ]; then
   if [ $(uname -s) == "Linux" ]; then
     envlist=py\{27,33,34,35,36\}-python
     envlist=py\{27,33,34,35,36\}-python
   else
   else
@@ -293,11 +222,9 @@ build_python() {
 
 
 build_python_cpp() {
 build_python_cpp() {
   internal_build_cpp
   internal_build_cpp
-  internal_install_python_deps
   export LD_LIBRARY_PATH=../src/.libs # for Linux
   export LD_LIBRARY_PATH=../src/.libs # for Linux
   export DYLD_LIBRARY_PATH=../src/.libs # for OS X
   export DYLD_LIBRARY_PATH=../src/.libs # for OS X
   cd python
   cd python
-  # Only test Python 3.x on Linux
   if [ $(uname -s) == "Linux" ]; then
   if [ $(uname -s) == "Linux" ]; then
     envlist=py\{27,33,34,35,36\}-cpp
     envlist=py\{27,33,34,35,36\}-cpp
   else
   else
@@ -325,18 +252,24 @@ build_ruby22() {
   internal_build_cpp  # For conformance tests.
   internal_build_cpp  # For conformance tests.
   cd ruby && bash travis-test.sh ruby-2.2 && cd ..
   cd ruby && bash travis-test.sh ruby-2.2 && cd ..
 }
 }
-build_jruby() {
+build_ruby23() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh ruby-2.3 && cd ..
+}
+build_ruby24() {
   internal_build_cpp  # For conformance tests.
   internal_build_cpp  # For conformance tests.
-  # TODO(xiaofeng): Upgrade to jruby-9.x. There are some broken jests to be
-  # fixed.
-  cd ruby && bash travis-test.sh jruby-1.7 && cd ..
+  cd ruby && bash travis-test.sh ruby-2.4 && cd ..
+}
+build_ruby25() {
+  internal_build_cpp  # For conformance tests.
+  cd ruby && bash travis-test.sh ruby-2.5.0 && cd ..
 }
 }
 build_ruby_all() {
 build_ruby_all() {
   build_ruby21
   build_ruby21
   build_ruby22
   build_ruby22
-  # TODO(teboring): Disable jruby test temperarily for it randomly fails.
-  # https://grpc-testing.appspot.com/job/protobuf_pull_request/735/consoleFull.
-  # build_jruby
+  build_ruby23
+  build_ruby24
+  build_ruby25
 }
 }
 
 
 build_javascript() {
 build_javascript() {
@@ -617,14 +550,6 @@ build_php_all() {
   build_php_compatibility
   build_php_compatibility
 }
 }
 
 
-# Note: travis currently does not support testing more than one language so the
-# .travis.yml cheats and claims to only be cpp.  If they add multiple language
-# support, this should probably get updated to install steps and/or
-# rvm/gemfile/jdk/etc. entries rather than manually doing the work.
-
-# .travis.yml uses matrix.exclude to block the cases where app-get can't be
-# use to install things.
-
 # -------- main --------
 # -------- main --------
 
 
 if [ "$#" -ne 1 ]; then
 if [ "$#" -ne 1 ]; then
@@ -635,8 +560,6 @@ Usage: $0 { cpp |
             java_jdk7 |
             java_jdk7 |
             java_oracle7 |
             java_oracle7 |
             java_compatibility |
             java_compatibility |
-            javanano_jdk7 |
-            javanano_oracle7 |
             objectivec_ios |
             objectivec_ios |
             objectivec_ios_debug |
             objectivec_ios_debug |
             objectivec_ios_release |
             objectivec_ios_release |
@@ -665,4 +588,5 @@ fi
 
 
 set -e  # exit immediately on error
 set -e  # exit immediately on error
 set -x  # display all commands
 set -x  # display all commands
+cd $(dirname $0)
 eval "build_$1"
 eval "build_$1"