1#!/bin/bash 2# 3# Build and runs tests for the protobuf project. We use this script to run 4# tests on kokoro (Ubuntu and MacOS). It can run locally as well but you 5# will need to make sure the required compilers/tools are available. 6 7# For when some other test needs the C++ main build, including protoc and 8# libprotobuf. 9internal_build_cpp() { 10 if [ -f src/protoc ]; then 11 # Already built. 12 return 13 fi 14 15 # Initialize any submodules. 16 git submodule update --init --recursive 17 18 ./autogen.sh 19 ./configure CXXFLAGS="-fPIC -std=c++11" # -fPIC is needed for python cpp test. 20 # See python/setup.py for more details 21 make -j$(nproc) 22} 23 24build_cpp() { 25 internal_build_cpp 26 make check -j$(nproc) || (cat src/test-suite.log; false) 27 cd conformance && make test_cpp && cd .. 28 29 # The benchmark code depends on cmake, so test if it is installed before 30 # trying to do the build. 31 if [[ $(type cmake 2>/dev/null) ]]; then 32 # Verify benchmarking code can build successfully. 33 cd benchmarks && make cpp-benchmark && cd .. 34 else 35 echo "" 36 echo "WARNING: Skipping validation of the bench marking code, cmake isn't installed." 37 echo "" 38 fi 39} 40 41build_cpp_tcmalloc() { 42 internal_build_cpp 43 ./configure LIBS=-ltcmalloc && make clean && make \ 44 PTHREAD_CFLAGS='-pthread -DGOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN' \ 45 check 46 cd src 47 PPROF_PATH=/usr/bin/google-pprof HEAPCHECK=strict ./protobuf-test 48} 49 50build_cpp_distcheck() { 51 grep -q -- "-Og" src/Makefile.am && 52 echo "The -Og flag is incompatible with Clang versions older than 4.0." && 53 exit 1 54 55 # Initialize any submodules. 56 git submodule update --init --recursive 57 ./autogen.sh 58 ./configure 59 make dist 60 61 # List all files that should be included in the distribution package. 62 git ls-files | grep "^\(java\|python\|objectivec\|csharp\|js\|ruby\|php\|cmake\|examples\|src/google/protobuf/.*\.proto\)" |\ 63 grep -v ".gitignore" | grep -v "java/compatibility_tests" |\ 64 grep -v "python/compatibility_tests" | grep -v "csharp/compatibility_tests" > dist.lst 65 # Unzip the dist tar file. 66 DIST=`ls *.tar.gz` 67 tar -xf $DIST 68 cd ${DIST//.tar.gz} 69 # Check if every file exists in the dist tar file. 70 FILES_MISSING="" 71 for FILE in $(<../dist.lst); do 72 [ -f "$FILE" ] || { 73 echo "$FILE is not found!" 74 FILES_MISSING="$FILE $FILES_MISSING" 75 } 76 done 77 cd .. 78 if [ ! -z "$FILES_MISSING" ]; then 79 echo "Missing files in EXTRA_DIST: $FILES_MISSING" 80 exit 1 81 fi 82 83 # Do the regular dist-check for C++. 84 make distcheck -j$(nproc) 85} 86 87build_dist_install() { 88 # Initialize any submodules. 89 git submodule update --init --recursive 90 ./autogen.sh 91 ./configure 92 make dist 93 94 # Unzip the dist tar file and install it. 95 DIST=`ls *.tar.gz` 96 tar -xf $DIST 97 pushd ${DIST//.tar.gz} 98 ./configure && make check -j4 && make install 99 100 export LD_LIBRARY_PATH=/usr/local/lib 101 102 # Try to install Java 103 pushd java 104 use_java jdk7 105 $MVN install 106 popd 107 108 # Try to install Python 109 virtualenv --no-site-packages venv 110 source venv/bin/activate 111 pushd python 112 python setup.py clean build sdist 113 pip install dist/protobuf-*.tar.gz 114 popd 115 deactivate 116 rm -rf python/venv 117} 118 119build_csharp() { 120 # Required for conformance tests and to regenerate protos. 121 internal_build_cpp 122 NUGET=/usr/local/bin/nuget.exe 123 124 # Disable some unwanted dotnet options 125 export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true 126 export DOTNET_CLI_TELEMETRY_OPTOUT=true 127 128 # TODO(jtattermusch): is this still needed with "first time experience" 129 # disabled? 130 # Perform "dotnet new" once to get the setup preprocessing out of the 131 # way. That spews a lot of output (including backspaces) into logs 132 # otherwise, and can cause problems. It doesn't matter if this step 133 # is performed multiple times; it's cheap after the first time anyway. 134 # (It also doesn't matter if it's unnecessary, which it will be on some 135 # systems. It's necessary on Jenkins in order to avoid unprintable 136 # characters appearing in the JUnit output.) 137 mkdir dotnettmp 138 (cd dotnettmp; dotnet new > /dev/null) 139 rm -rf dotnettmp 140 141 # Check that the protos haven't broken C# codegen. 142 # TODO(jonskeet): Fail if regenerating creates any changes. 143 csharp/generate_protos.sh 144 145 csharp/buildall.sh 146 cd conformance && make test_csharp && cd .. 147 148 # Run csharp compatibility test between 3.0.0 and the current version. 149 csharp/compatibility_tests/v3.0.0/test.sh 3.0.0 150} 151 152build_golang() { 153 # Go build needs `protoc`. 154 internal_build_cpp 155 # Add protoc to the path so that the examples build finds it. 156 export PATH="`pwd`/src:$PATH" 157 158 export GOPATH="$HOME/gocode" 159 mkdir -p "$GOPATH/src/github.com/protocolbuffers" 160 rm -f "$GOPATH/src/github.com/protocolbuffers/protobuf" 161 ln -s "`pwd`" "$GOPATH/src/github.com/protocolbuffers/protobuf" 162 export PATH="$GOPATH/bin:$PATH" 163 go get github.com/golang/protobuf/protoc-gen-go 164 165 cd examples && PROTO_PATH="-I../src -I." make gotest && cd .. 166} 167 168use_java() { 169 version=$1 170 case "$version" in 171 jdk7) 172 export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH 173 export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 174 ;; 175 oracle7) 176 export PATH=/usr/lib/jvm/java-7-oracle/bin:$PATH 177 export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 178 ;; 179 esac 180 181 MAVEN_LOCAL_REPOSITORY=/var/maven_local_repository 182 MVN="$MVN -e -X -Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$MAVEN_LOCAL_REPOSITORY" 183 184 which java 185 java -version 186 $MVN -version 187} 188 189# --batch-mode supresses download progress output that spams the logs. 190MVN="mvn --batch-mode" 191 192build_java() { 193 version=$1 194 dir=java_$version 195 # Java build needs `protoc`. 196 internal_build_cpp 197 cp -r java $dir 198 cd $dir && $MVN clean && $MVN test 199 cd ../.. 200} 201 202# The conformance tests are hard-coded to work with the $ROOT/java directory. 203# So this can't run in parallel with two different sets of tests. 204build_java_with_conformance_tests() { 205 # Java build needs `protoc`. 206 internal_build_cpp 207 cd java && $MVN test && $MVN install 208 cd util && $MVN package assembly:single 209 cd ../.. 210 cd conformance && make test_java && cd .. 211} 212 213build_java_jdk7() { 214 use_java jdk7 215 build_java_with_conformance_tests 216} 217build_java_oracle7() { 218 use_java oracle7 219 build_java oracle7 220} 221build_java_compatibility() { 222 use_java jdk7 223 internal_build_cpp 224 # Use the unit-tests extraced from 2.5.0 to test the compatibilty between 225 # 3.0.0-beta-4 and the current version. 226 cd java/compatibility_tests/v2.5.0 227 ./test.sh 3.0.0-beta-4 228} 229 230build_objectivec_ios() { 231 # Reused the build script that takes care of configuring and ensuring things 232 # are up to date. The OS X test runs the objc conformance test, so skip it 233 # here. 234 objectivec/DevTools/full_mac_build.sh \ 235 --core-only --skip-xcode-osx --skip-xcode-tvos --skip-objc-conformance "$@" 236} 237 238build_objectivec_ios_debug() { 239 build_objectivec_ios --skip-xcode-release 240} 241 242build_objectivec_ios_release() { 243 build_objectivec_ios --skip-xcode-debug 244} 245 246build_objectivec_osx() { 247 # Reused the build script that takes care of configuring and ensuring things 248 # are up to date. 249 objectivec/DevTools/full_mac_build.sh \ 250 --core-only --skip-xcode-ios --skip-xcode-tvos 251} 252 253build_objectivec_tvos() { 254 # Reused the build script that takes care of configuring and ensuring things 255 # are up to date. The OS X test runs the objc conformance test, so skip it 256 # here. 257 objectivec/DevTools/full_mac_build.sh \ 258 --core-only --skip-xcode-ios --skip-xcode-osx --skip-objc-conformance "$@" 259} 260 261build_objectivec_tvos_debug() { 262 build_objectivec_tvos --skip-xcode-release 263} 264 265build_objectivec_tvos_release() { 266 build_objectivec_tvos --skip-xcode-debug 267} 268 269build_objectivec_cocoapods_integration() { 270 # Update pod to the latest version. 271 gem install cocoapods --no_document 272 objectivec/Tests/CocoaPods/run_tests.sh 273} 274 275build_python() { 276 internal_build_cpp 277 cd python 278 if [ $(uname -s) == "Linux" ]; then 279 envlist=py\{27,33,34,35,36\}-python 280 else 281 envlist=py27-python 282 fi 283 tox -e $envlist 284 cd .. 285} 286 287build_python_version() { 288 internal_build_cpp 289 cd python 290 envlist=$1 291 tox -e $envlist 292 cd .. 293} 294 295build_python27() { 296 build_python_version py27-python 297} 298 299build_python33() { 300 build_python_version py33-python 301} 302 303build_python34() { 304 build_python_version py34-python 305} 306 307build_python35() { 308 build_python_version py35-python 309} 310 311build_python36() { 312 build_python_version py36-python 313} 314 315build_python37() { 316 build_python_version py37-python 317} 318 319build_python_cpp() { 320 internal_build_cpp 321 export LD_LIBRARY_PATH=../src/.libs # for Linux 322 export DYLD_LIBRARY_PATH=../src/.libs # for OS X 323 cd python 324 if [ $(uname -s) == "Linux" ]; then 325 envlist=py\{27,33,34,35,36\}-cpp 326 else 327 envlist=py27-cpp 328 fi 329 tox -e $envlist 330 cd .. 331} 332 333build_python_cpp_version() { 334 internal_build_cpp 335 export LD_LIBRARY_PATH=../src/.libs # for Linux 336 export DYLD_LIBRARY_PATH=../src/.libs # for OS X 337 cd python 338 envlist=$1 339 tox -e $envlist 340 cd .. 341} 342 343build_python27_cpp() { 344 build_python_cpp_version py27-cpp 345} 346 347build_python33_cpp() { 348 build_python_cpp_version py33-cpp 349} 350 351build_python34_cpp() { 352 build_python_cpp_version py34-cpp 353} 354 355build_python35_cpp() { 356 build_python_cpp_version py35-cpp 357} 358 359build_python36_cpp() { 360 build_python_cpp_version py36-cpp 361} 362 363build_python37_cpp() { 364 build_python_cpp_version py37-cpp 365} 366 367build_python_compatibility() { 368 internal_build_cpp 369 # Use the unit-tests extraced from 2.5.0 to test the compatibilty. 370 cd python/compatibility_tests/v2.5.0 371 # Test between 2.5.0 and the current version. 372 ./test.sh 2.5.0 373 # Test between 3.0.0-beta-1 and the current version. 374 ./test.sh 3.0.0-beta-1 375} 376 377build_ruby23() { 378 internal_build_cpp # For conformance tests. 379 cd ruby && bash travis-test.sh ruby-2.3.8 && cd .. 380} 381build_ruby24() { 382 internal_build_cpp # For conformance tests. 383 cd ruby && bash travis-test.sh ruby-2.4 && cd .. 384} 385build_ruby25() { 386 internal_build_cpp # For conformance tests. 387 cd ruby && bash travis-test.sh ruby-2.5.1 && cd .. 388} 389build_ruby26() { 390 internal_build_cpp # For conformance tests. 391 cd ruby && bash travis-test.sh ruby-2.6.0 && cd .. 392} 393 394build_javascript() { 395 internal_build_cpp 396 cd js && npm install && npm test && cd .. 397 cd conformance && make test_nodejs && cd .. 398} 399 400generate_php_test_proto() { 401 internal_build_cpp 402 pushd php/tests 403 # Generate test file 404 rm -rf generated 405 mkdir generated 406 ../../src/protoc --php_out=generated \ 407 -I../../src -I. \ 408 proto/empty/echo.proto \ 409 proto/test.proto \ 410 proto/test_include.proto \ 411 proto/test_no_namespace.proto \ 412 proto/test_prefix.proto \ 413 proto/test_php_namespace.proto \ 414 proto/test_empty_php_namespace.proto \ 415 proto/test_reserved_enum_lower.proto \ 416 proto/test_reserved_enum_upper.proto \ 417 proto/test_reserved_enum_value_lower.proto \ 418 proto/test_reserved_enum_value_upper.proto \ 419 proto/test_reserved_message_lower.proto \ 420 proto/test_reserved_message_upper.proto \ 421 proto/test_service.proto \ 422 proto/test_service_namespace.proto \ 423 proto/test_wrapper_type_setters.proto \ 424 proto/test_descriptors.proto 425 pushd ../../src 426 ./protoc --php_out=../php/tests/generated -I../php/tests -I. \ 427 ../php/tests/proto/test_import_descriptor_proto.proto 428 popd 429 popd 430} 431 432use_php() { 433 VERSION=$1 434 export PATH=/usr/local/php-${VERSION}/bin:$PATH 435 export CPLUS_INCLUDE_PATH=/usr/local/php-${VERSION}/include/php/main:/usr/local/php-${VERSION}/include/php/:$CPLUS_INCLUDE_PATH 436 export C_INCLUDE_PATH=/usr/local/php-${VERSION}/include/php/main:/usr/local/php-${VERSION}/include/php/:$C_INCLUDE_PATH 437 generate_php_test_proto 438} 439 440use_php_zts() { 441 VERSION=$1 442 export PATH=/usr/local/php-${VERSION}-zts/bin:$PATH 443 export CPLUS_INCLUDE_PATH=/usr/local/php-${VERSION}-zts/include/php/main:/usr/local/php-${VERSION}-zts/include/php/:$CPLUS_INCLUDE_PATH 444 export C_INCLUDE_PATH=/usr/local/php-${VERSION}-zts/include/php/main:/usr/local/php-${VERSION}-zts/include/php/:$C_INCLUDE_PATH 445 generate_php_test_proto 446} 447 448use_php_bc() { 449 VERSION=$1 450 export PATH=/usr/local/php-${VERSION}-bc/bin:$PATH 451 export CPLUS_INCLUDE_PATH=/usr/local/php-${VERSION}-bc/include/php/main:/usr/local/php-${VERSION}-bc/include/php/:$CPLUS_INCLUDE_PATH 452 export C_INCLUDE_PATH=/usr/local/php-${VERSION}-bc/include/php/main:/usr/local/php-${VERSION}-bc/include/php/:$C_INCLUDE_PATH 453 generate_php_test_proto 454} 455 456build_php5.5() { 457 use_php 5.5 458 459 pushd php 460 rm -rf vendor 461 composer update 462 ./vendor/bin/phpunit 463 popd 464 pushd conformance 465 make test_php 466 popd 467} 468 469build_php5.5_c() { 470 use_php 5.5 471 pushd php/tests 472 /bin/bash ./test.sh 5.5 473 popd 474 # TODO(teboring): Add it back 475 # pushd conformance 476 # make test_php_c 477 # popd 478} 479 480build_php5.5_mixed() { 481 use_php 5.5 482 pushd php 483 rm -rf vendor 484 composer update 485 /bin/bash ./tests/compile_extension.sh ./ext/google/protobuf 486 php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit 487 popd 488} 489 490build_php5.5_zts_c() { 491 use_php_zts 5.5 492 cd php/tests && /bin/bash ./test.sh 5.5-zts && cd ../.. 493 # TODO(teboring): Add it back 494 # pushd conformance 495 # make test_php_zts_c 496 # popd 497} 498 499build_php5.6() { 500 use_php 5.6 501 pushd php 502 rm -rf vendor 503 composer update 504 ./vendor/bin/phpunit 505 popd 506 pushd conformance 507 make test_php 508 popd 509} 510 511build_php5.6_c() { 512 use_php 5.6 513 cd php/tests && /bin/bash ./test.sh 5.6 && cd ../.. 514 # TODO(teboring): Add it back 515 # pushd conformance 516 # make test_php_c 517 # popd 518} 519 520build_php5.6_mixed() { 521 use_php 5.6 522 pushd php 523 rm -rf vendor 524 composer update 525 /bin/bash ./tests/compile_extension.sh ./ext/google/protobuf 526 php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit 527 popd 528} 529 530build_php5.6_zts_c() { 531 use_php_zts 5.6 532 cd php/tests && /bin/bash ./test.sh 5.6-zts && cd ../.. 533 # TODO(teboring): Add it back 534 # pushd conformance 535 # make test_php_zts_c 536 # popd 537} 538 539build_php5.6_mac() { 540 generate_php_test_proto 541 # Install PHP 542 curl -s https://php-osx.liip.ch/install.sh | bash -s 5.6 543 PHP_FOLDER=`find /usr/local -type d -name "php5-5.6*"` # The folder name may change upon time 544 export PATH="$PHP_FOLDER/bin:$PATH" 545 546 # Install phpunit 547 curl https://phar.phpunit.de/phpunit-5.6.8.phar -L -o phpunit.phar 548 chmod +x phpunit.phar 549 sudo mv phpunit.phar /usr/local/bin/phpunit 550 551 # Install valgrind 552 echo "#! /bin/bash" > valgrind 553 chmod ug+x valgrind 554 sudo mv valgrind /usr/local/bin/valgrind 555 556 # Test 557 cd php/tests && /bin/bash ./test.sh && cd ../.. 558 # TODO(teboring): Add it back 559 # pushd conformance 560 # make test_php_c 561 # popd 562} 563 564build_php7.0() { 565 use_php 7.0 566 pushd php 567 rm -rf vendor 568 composer update 569 ./vendor/bin/phpunit 570 popd 571 pushd conformance 572 make test_php 573 popd 574} 575 576build_php7.0_c() { 577 use_php 7.0 578 cd php/tests && /bin/bash ./test.sh 7.0 && cd ../.. 579 # TODO(teboring): Add it back 580 # pushd conformance 581 # make test_php_c 582 # popd 583} 584 585build_php7.0_mixed() { 586 use_php 7.0 587 pushd php 588 rm -rf vendor 589 composer update 590 /bin/bash ./tests/compile_extension.sh ./ext/google/protobuf 591 php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit 592 popd 593} 594 595build_php7.0_zts_c() { 596 use_php_zts 7.0 597 cd php/tests && /bin/bash ./test.sh 7.0-zts && cd ../.. 598 # TODO(teboring): Add it back. 599 # pushd conformance 600 # make test_php_zts_c 601 # popd 602} 603 604build_php7.0_mac() { 605 generate_php_test_proto 606 # Install PHP 607 curl -s https://php-osx.liip.ch/install.sh | bash -s 7.0 608 PHP_FOLDER=`find /usr/local -type d -name "php7-7.0*"` # The folder name may change upon time 609 export PATH="$PHP_FOLDER/bin:$PATH" 610 611 # Install phpunit 612 curl https://phar.phpunit.de/phpunit-5.6.0.phar -L -o phpunit.phar 613 chmod +x phpunit.phar 614 sudo mv phpunit.phar /usr/local/bin/phpunit 615 616 # Install valgrind 617 echo "#! /bin/bash" > valgrind 618 chmod ug+x valgrind 619 sudo mv valgrind /usr/local/bin/valgrind 620 621 # Test 622 cd php/tests && /bin/bash ./test.sh && cd ../.. 623 # TODO(teboring): Add it back 624 # pushd conformance 625 # make test_php_c 626 # popd 627} 628 629build_php_compatibility() { 630 internal_build_cpp 631 php/tests/compatibility_test.sh 632} 633 634build_php7.1() { 635 use_php 7.1 636 pushd php 637 rm -rf vendor 638 composer update 639 ./vendor/bin/phpunit 640 popd 641 pushd conformance 642 make test_php 643 popd 644} 645 646build_php7.1_c() { 647 ENABLE_CONFORMANCE_TEST=$1 648 use_php 7.1 649 cd php/tests && /bin/bash ./test.sh 7.1 && cd ../.. 650 if [ "$ENABLE_CONFORMANCE_TEST" = "true" ] 651 then 652 pushd conformance 653 make test_php_c 654 popd 655 fi 656} 657 658build_php7.1_mixed() { 659 use_php 7.1 660 pushd php 661 rm -rf vendor 662 composer update 663 /bin/bash ./tests/compile_extension.sh ./ext/google/protobuf 664 php -dextension=./ext/google/protobuf/modules/protobuf.so ./vendor/bin/phpunit 665 popd 666} 667 668build_php7.1_zts_c() { 669 use_php_zts 7.1 670 cd php/tests && /bin/bash ./test.sh 7.1-zts && cd ../.. 671 pushd conformance 672 # make test_php_c 673 popd 674} 675 676build_php_all_32() { 677 build_php5.5 678 build_php5.6 679 build_php7.0 680 build_php7.1 681 build_php5.5_c 682 build_php5.6_c 683 build_php7.0_c 684 build_php7.1_c $1 685 build_php5.5_mixed 686 build_php5.6_mixed 687 build_php7.0_mixed 688 build_php7.1_mixed 689 build_php5.5_zts_c 690 build_php5.6_zts_c 691 build_php7.0_zts_c 692 build_php7.1_zts_c 693} 694 695build_php_all() { 696 build_php_all_32 true 697 build_php_compatibility 698} 699 700build_benchmark() { 701 use_php 7.2 702 cd kokoro/linux/benchmark && ./run.sh 703} 704 705# -------- main -------- 706 707if [ "$#" -ne 1 ]; then 708 echo " 709Usage: $0 { cpp | 710 cpp_distcheck | 711 csharp | 712 java_jdk7 | 713 java_oracle7 | 714 java_compatibility | 715 objectivec_ios | 716 objectivec_ios_debug | 717 objectivec_ios_release | 718 objectivec_osx | 719 objectivec_tvos | 720 objectivec_tvos_debug | 721 objectivec_tvos_release | 722 objectivec_cocoapods_integration | 723 python | 724 python_cpp | 725 python_compatibility | 726 ruby23 | 727 ruby24 | 728 ruby25 | 729 ruby26 | 730 jruby | 731 ruby_all | 732 php5.5 | 733 php5.5_c | 734 php5.6 | 735 php5.6_c | 736 php7.0 | 737 php7.0_c | 738 php_compatibility | 739 php7.1 | 740 php7.1_c | 741 php_all | 742 dist_install | 743 benchmark) 744" 745 exit 1 746fi 747 748set -e # exit immediately on error 749set -x # display all commands 750cd $(dirname $0) 751eval "build_$1" 752