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. 9LAST_RELEASED=3.9.0 10 11internal_build_cpp() { 12 if [ -f src/protoc ]; then 13 # Already built. 14 return 15 fi 16 17 # Initialize any submodules. 18 git submodule update --init --recursive 19 20 ./autogen.sh 21 ./configure CXXFLAGS="-fPIC -std=c++11" # -fPIC is needed for python cpp test. 22 # See python/setup.py for more details 23 make -j$(nproc) 24} 25 26build_cpp() { 27 internal_build_cpp 28 make check -j$(nproc) || (cat src/test-suite.log; false) 29 cd conformance && make test_cpp && cd .. 30} 31 32build_cpp_tcmalloc() { 33 internal_build_cpp 34 ./configure LIBS=-ltcmalloc && make clean && make \ 35 PTHREAD_CFLAGS='-pthread -DGOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN' \ 36 check 37 cd src 38 PPROF_PATH=/usr/bin/google-pprof HEAPCHECK=strict ./protobuf-test 39} 40 41build_cpp_distcheck() { 42 grep -q -- "-Og" src/Makefile.am && 43 echo "The -Og flag is incompatible with Clang versions older than 4.0." && 44 exit 1 45 46 # Initialize any submodules. 47 git submodule update --init --recursive 48 ./autogen.sh 49 ./configure 50 make dist 51 52 # List all files that should be included in the distribution package. 53 git ls-files | grep "^\(java\|python\|objectivec\|csharp\|js\|ruby\|php\|cmake\|examples\|src/google/protobuf/.*\.proto\)" |\ 54 grep -v ".gitignore" | grep -v "java/lite/proguard.pgcfg" |\ 55 grep -v "python/compatibility_tests" | grep -v "python/docs" | grep -v "python/.repo-metadata.json" |\ 56 grep -v "python/protobuf_distutils" | grep -v "csharp/compatibility_tests" > dist.lst 57 # Unzip the dist tar file. 58 DIST=`ls *.tar.gz` 59 tar -xf $DIST 60 cd ${DIST//.tar.gz} 61 # Check if every file exists in the dist tar file. 62 FILES_MISSING="" 63 for FILE in $(<../dist.lst); do 64 [ -f "$FILE" ] || { 65 echo "$FILE is not found!" 66 FILES_MISSING="$FILE $FILES_MISSING" 67 } 68 done 69 cd .. 70 if [ ! -z "$FILES_MISSING" ]; then 71 echo "Missing files in EXTRA_DIST: $FILES_MISSING" 72 exit 1 73 fi 74 75 # Do the regular dist-check for C++. 76 make distcheck -j$(nproc) 77} 78 79build_dist_install() { 80 # Create a symlink pointing to python2 and put it at the beginning of $PATH. 81 # This is necessary because the googletest build system involves a Python 82 # script that is not compatible with Python 3. More recent googletest 83 # versions have fixed this, but they have also removed the autotools build 84 # system support that we rely on. This is a temporary workaround to keep the 85 # googletest build working when the default python binary is Python 3. 86 mkdir tmp || true 87 pushd tmp 88 ln -s /usr/bin/python2 ./python 89 popd 90 PATH=$PWD/tmp:$PATH 91 92 # Initialize any submodules. 93 git submodule update --init --recursive 94 ./autogen.sh 95 ./configure 96 make dist 97 98 # Unzip the dist tar file and install it. 99 DIST=`ls *.tar.gz` 100 tar -xf $DIST 101 pushd ${DIST//.tar.gz} 102 ./configure && make check -j4 && make install 103 104 export LD_LIBRARY_PATH=/usr/local/lib 105 106 # Try to install Java 107 pushd java 108 use_java jdk11 109 $MVN install 110 popd 111 112 # Try to install Python 113 python3 -m venv venv 114 source venv/bin/activate 115 pushd python 116 python3 setup.py clean build sdist 117 pip3 install dist/protobuf-*.tar.gz 118 popd 119 deactivate 120 rm -rf python/venv 121} 122 123build_csharp() { 124 # Required for conformance tests and to regenerate protos. 125 internal_build_cpp 126 NUGET=/usr/local/bin/nuget.exe 127 128 # Disable some unwanted dotnet options 129 export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true 130 export DOTNET_CLI_TELEMETRY_OPTOUT=true 131 132 # TODO(jtattermusch): is this still needed with "first time experience" 133 # disabled? 134 # Perform "dotnet new" once to get the setup preprocessing out of the 135 # way. That spews a lot of output (including backspaces) into logs 136 # otherwise, and can cause problems. It doesn't matter if this step 137 # is performed multiple times; it's cheap after the first time anyway. 138 # (It also doesn't matter if it's unnecessary, which it will be on some 139 # systems. It's necessary on Jenkins in order to avoid unprintable 140 # characters appearing in the JUnit output.) 141 mkdir dotnettmp 142 (cd dotnettmp; dotnet new > /dev/null) 143 rm -rf dotnettmp 144 145 # Check that the protos haven't broken C# codegen. 146 # TODO(jonskeet): Fail if regenerating creates any changes. 147 csharp/generate_protos.sh 148 149 csharp/buildall.sh 150 cd conformance && make test_csharp && cd .. 151 152 # Run csharp compatibility test between 3.0.0 and the current version. 153 csharp/compatibility_tests/v3.0.0/test.sh 3.0.0 154 155 # Run csharp compatibility test between last released and the current version. 156 csharp/compatibility_tests/v3.0.0/test.sh $LAST_RELEASED 157} 158 159build_golang() { 160 # Go build needs `protoc`. 161 internal_build_cpp 162 # Add protoc to the path so that the examples build finds it. 163 export PATH="`pwd`/src:$PATH" 164 165 export GOPATH="$HOME/gocode" 166 mkdir -p "$GOPATH/src/github.com/protocolbuffers" 167 mkdir -p "$GOPATH/src/github.com/golang" 168 rm -f "$GOPATH/src/github.com/protocolbuffers/protobuf" 169 rm -f "$GOPATH/src/github.com/golang/protobuf" 170 ln -s "`pwd`" "$GOPATH/src/github.com/protocolbuffers/protobuf" 171 export PATH="$GOPATH/bin:$PATH" 172 (cd $GOPATH/src/github.com/golang && git clone https://github.com/golang/protobuf.git && cd protobuf && git checkout v1.3.5) 173 go install github.com/golang/protobuf/protoc-gen-go 174 175 cd examples && PROTO_PATH="-I../src -I." make gotest && cd .. 176} 177 178use_java() { 179 version=$1 180 case "$version" in 181 jdk11) 182 export PATH=/usr/lib/jvm/java-11-openjdk-amd64/bin:$PATH 183 export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 184 ;; 185 jdk8) 186 export PATH=/usr/lib/jvm/java-8-openjdk-amd64/bin:$PATH 187 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 188 ;; 189 jdk7) 190 export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH 191 export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 192 ;; 193 oracle7) 194 export PATH=/usr/lib/jvm/java-7-oracle/bin:$PATH 195 export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 196 ;; 197 esac 198 199 MAVEN_LOCAL_REPOSITORY=/var/maven_local_repository 200 MVN="$MVN -e --quiet -Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$MAVEN_LOCAL_REPOSITORY" 201 202 which java 203 java -version 204 $MVN -version 205} 206 207# --batch-mode suppresses download progress output that spams the logs. 208MVN="mvn --batch-mode" 209 210internal_build_java() { 211 version=$1 212 dir=java_$version 213 # Java build needs `protoc`. 214 internal_build_cpp 215 cp -r java $dir 216 cd $dir && $MVN clean 217 # Skip tests here - callers will decide what tests they want to run 218 $MVN install -Dmaven.test.skip=true 219} 220 221build_java() { 222 version=$1 223 internal_build_java $version 224 # Skip the Kotlin tests on Oracle 7 225 if [ "$version" == "oracle7" ]; then 226 $MVN test -pl bom,lite,core,util 227 else 228 $MVN test 229 fi 230 cd ../.. 231} 232 233# The conformance tests are hard-coded to work with the $ROOT/java directory. 234# So this can't run in parallel with two different sets of tests. 235build_java_with_conformance_tests() { 236 # Java build needs `protoc`. 237 internal_build_cpp 238 # This local installation avoids the problem caused by a new version not yet in Maven Central 239 cd java/bom && $MVN install 240 cd ../.. 241 cd java/core && $MVN test && $MVN install 242 cd ../lite && $MVN test && $MVN install 243 cd ../util && $MVN test && $MVN install && $MVN package assembly:single 244 if [ "$version" == "jdk8" ]; then 245 cd ../kotlin && $MVN test && $MVN install 246 cd ../kotlin-lite && $MVN test && $MVN install 247 fi 248 cd ../.. 249 cd conformance && make test_java && cd .. 250} 251 252build_java_jdk7() { 253 use_java jdk7 254 build_java_with_conformance_tests 255} 256build_java_oracle7() { 257 use_java oracle7 258 build_java oracle7 259} 260build_java_linkage_monitor() { 261 # Linkage Monitor checks compatibility with other Google libraries 262 # https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/linkage-monitor 263 264 use_java jdk11 265 internal_build_cpp 266 267 # Linkage Monitor uses $HOME/.m2 local repository 268 MVN="mvn -e -B -Dhttps.protocols=TLSv1.2" 269 cd java 270 # Installs the snapshot version locally 271 $MVN install -Dmaven.test.skip=true 272 273 # Linkage Monitor uses the snapshot versions installed in $HOME/.m2 to verify compatibility 274 JAR=linkage-monitor-latest-all-deps.jar 275 curl -v -O "https://storage.googleapis.com/cloud-opensource-java-linkage-monitor/${JAR}" 276 # Fails if there's new linkage errors compared with baseline 277 java -jar $JAR com.google.cloud:libraries-bom 278} 279 280build_objectivec_ios() { 281 # Reused the build script that takes care of configuring and ensuring things 282 # are up to date. The OS X test runs the objc conformance test, so skip it 283 # here. 284 objectivec/DevTools/full_mac_build.sh \ 285 --core-only --skip-xcode-osx --skip-xcode-tvos --skip-objc-conformance "$@" 286} 287 288build_objectivec_ios_debug() { 289 build_objectivec_ios --skip-xcode-release 290} 291 292build_objectivec_ios_release() { 293 build_objectivec_ios --skip-xcode-debug 294} 295 296build_objectivec_osx() { 297 # Reused the build script that takes care of configuring and ensuring things 298 # are up to date. 299 objectivec/DevTools/full_mac_build.sh \ 300 --core-only --skip-xcode-ios --skip-xcode-tvos 301} 302 303build_objectivec_tvos() { 304 # Reused the build script that takes care of configuring and ensuring things 305 # are up to date. The OS X test runs the objc conformance test, so skip it 306 # here. 307 objectivec/DevTools/full_mac_build.sh \ 308 --core-only --skip-xcode-ios --skip-xcode-osx --skip-objc-conformance "$@" 309} 310 311build_objectivec_tvos_debug() { 312 build_objectivec_tvos --skip-xcode-release 313} 314 315build_objectivec_tvos_release() { 316 build_objectivec_tvos --skip-xcode-debug 317} 318 319build_objectivec_cocoapods_integration() { 320 objectivec/Tests/CocoaPods/run_tests.sh 321} 322 323build_python() { 324 internal_build_cpp 325 cd python 326 tox --skip-missing-interpreters 327 cd .. 328} 329 330build_python_version() { 331 internal_build_cpp 332 cd python 333 envlist=$1 334 tox -e $envlist 335 cd .. 336} 337 338build_python37() { 339 build_python_version py37-python 340} 341 342build_python38() { 343 build_python_version py38-python 344} 345 346build_python39() { 347 build_python_version py39-python 348} 349 350build_python310() { 351 build_python_version py310-python 352} 353 354build_python_cpp() { 355 internal_build_cpp 356 export LD_LIBRARY_PATH=../src/.libs # for Linux 357 export DYLD_LIBRARY_PATH=../src/.libs # for OS X 358 cd python 359 tox --skip-missing-interpreters 360 cd .. 361} 362 363build_python_cpp_version() { 364 internal_build_cpp 365 export LD_LIBRARY_PATH=../src/.libs # for Linux 366 export DYLD_LIBRARY_PATH=../src/.libs # for OS X 367 cd python 368 envlist=$1 369 tox -e $envlist 370 cd .. 371} 372 373build_python37_cpp() { 374 build_python_cpp_version py37-cpp 375} 376 377build_python38_cpp() { 378 build_python_cpp_version py38-cpp 379} 380 381build_python39_cpp() { 382 build_python_cpp_version py39-cpp 383} 384 385build_python310_cpp() { 386 build_python_cpp_version py310-cpp 387} 388 389 390build_ruby23() { 391 internal_build_cpp # For conformance tests. 392 cd ruby && bash travis-test.sh ruby-2.3.8 && cd .. 393} 394build_ruby24() { 395 internal_build_cpp # For conformance tests. 396 cd ruby && bash travis-test.sh ruby-2.4 && cd .. 397} 398build_ruby25() { 399 internal_build_cpp # For conformance tests. 400 cd ruby && bash travis-test.sh ruby-2.5.1 && cd .. 401} 402build_ruby26() { 403 internal_build_cpp # For conformance tests. 404 cd ruby && bash travis-test.sh ruby-2.6.0 && cd .. 405} 406build_ruby27() { 407 internal_build_cpp # For conformance tests. 408 cd ruby && bash travis-test.sh ruby-2.7.0 && cd .. 409} 410build_ruby30() { 411 internal_build_cpp # For conformance tests. 412 cd ruby && bash travis-test.sh ruby-3.0.2 && cd .. 413} 414build_ruby31() { 415 internal_build_cpp # For conformance tests. 416 cd ruby && bash travis-test.sh ruby-3.1.0 && cd .. 417} 418 419build_jruby92() { 420 internal_build_cpp # For conformance tests. 421 internal_build_java jdk8 && cd .. # For Maven protobuf jar with local changes 422 cd ruby && bash travis-test.sh jruby-9.2.20.1 && cd .. 423} 424 425build_jruby93() { 426 internal_build_cpp # For conformance tests. 427 internal_build_java jdk8 && cd .. # For Maven protobuf jar with local changes 428 cd ruby && bash travis-test.sh jruby-9.3.3.0 && cd .. 429} 430 431build_javascript() { 432 internal_build_cpp 433 NODE_VERSION=node-v12.16.3-darwin-x64 434 NODE_TGZ="$NODE_VERSION.tar.gz" 435 pushd /tmp 436 curl -OL https://nodejs.org/dist/v12.16.3/$NODE_TGZ 437 tar zxvf $NODE_TGZ 438 export PATH=$PATH:`pwd`/$NODE_VERSION/bin 439 popd 440 cd js && npm install && npm test && cd .. 441 cd conformance && make test_nodejs && cd .. 442} 443 444use_php() { 445 VERSION=$1 446 export PATH=/usr/local/php-${VERSION}/bin:$PATH 447 internal_build_cpp 448} 449 450build_php() { 451 use_php $1 452 pushd php 453 rm -rf vendor 454 php -v 455 php -m 456 composer update 457 composer test 458 popd 459 (cd conformance && make test_php) 460} 461 462test_php_c() { 463 pushd php 464 rm -rf vendor 465 php -v 466 php -m 467 composer update 468 composer test_c 469 popd 470 (cd conformance && make test_php_c) 471} 472 473build_php_c() { 474 use_php $1 475 test_php_c 476} 477 478build_php7.0_mac() { 479 internal_build_cpp 480 # Install PHP 481 curl -s https://php-osx.liip.ch/install.sh | bash -s 7.0 482 PHP_FOLDER=`find /usr/local -type d -name "php5-7.0*"` # The folder name may change upon time 483 test ! -z "$PHP_FOLDER" 484 export PATH="$PHP_FOLDER/bin:$PATH" 485 486 # Install Composer 487 wget https://getcomposer.org/download/2.0.13/composer.phar --progress=dot:mega -O /usr/local/bin/composer 488 chmod a+x /usr/local/bin/composer 489 490 # Install valgrind 491 echo "#! /bin/bash" > valgrind 492 chmod ug+x valgrind 493 sudo mv valgrind /usr/local/bin/valgrind 494 495 # Test 496 test_php_c 497} 498 499build_php7.3_mac() { 500 internal_build_cpp 501 # Install PHP 502 # We can't test PHP 7.4 with these binaries yet: 503 # https://github.com/liip/php-osx/issues/276 504 curl -s https://php-osx.liip.ch/install.sh | bash -s 7.3 505 PHP_FOLDER=`find /usr/local -type d -name "php5-7.3*"` # The folder name may change upon time 506 test ! -z "$PHP_FOLDER" 507 export PATH="$PHP_FOLDER/bin:$PATH" 508 509 # Install Composer 510 wget https://getcomposer.org/download/2.0.13/composer.phar --progress=dot:mega -O /usr/local/bin/composer 511 chmod a+x /usr/local/bin/composer 512 513 # Install valgrind 514 echo "#! /bin/bash" > valgrind 515 chmod ug+x valgrind 516 sudo mv valgrind /usr/local/bin/valgrind 517 518 # Test 519 test_php_c 520} 521 522build_php_compatibility() { 523 internal_build_cpp 524 php/tests/compatibility_test.sh $LAST_RELEASED 525} 526 527build_php_multirequest() { 528 use_php 7.4 529 php/tests/multirequest.sh 530} 531 532build_php8.0_all() { 533 build_php 8.0 534 build_php 8.1 535 build_php_c 8.0 536 build_php_c 8.1 537} 538 539build_php_all_32() { 540 build_php 7.0 541 build_php 7.1 542 build_php 7.4 543 build_php_c 7.0 544 build_php_c 7.1 545 build_php_c 7.4 546 build_php_c 7.1-zts 547 build_php_c 7.2-zts 548 build_php_c 7.5-zts 549} 550 551build_php_all() { 552 build_php_all_32 553 build_php_multirequest 554 build_php_compatibility 555} 556 557build_benchmark() { 558 use_php 7.2 559 cd kokoro/linux/benchmark && ./run.sh 560} 561 562# -------- main -------- 563 564if [ "$#" -ne 1 ]; then 565 echo " 566Usage: $0 { cpp | 567 cpp_distcheck | 568 csharp | 569 java_jdk7 | 570 java_oracle7 | 571 java_linkage_monitor | 572 objectivec_ios | 573 objectivec_ios_debug | 574 objectivec_ios_release | 575 objectivec_osx | 576 objectivec_tvos | 577 objectivec_tvos_debug | 578 objectivec_tvos_release | 579 objectivec_cocoapods_integration | 580 python | 581 python_cpp | 582 python_compatibility | 583 ruby23 | 584 ruby24 | 585 ruby25 | 586 ruby26 | 587 ruby27 | 588 ruby30 | 589 ruby31 | 590 jruby92 | 591 jruby93 | 592 ruby_all | 593 php_all | 594 php_all_32 | 595 php7.0_mac | 596 php7.3_mac | 597 dist_install | 598 benchmark) 599" 600 exit 1 601fi 602 603set -e # exit immediately on error 604set -x # display all commands 605cd $(dirname $0) 606eval "build_$1" 607