Add python compatibility tests against v2.5.0 amd run on Travis.

This commit is contained in:
Jie Luo 2017-01-23 15:11:00 -08:00
parent 140e28d12e
commit ea51149100
6 changed files with 220 additions and 4 deletions

View File

@ -63,6 +63,10 @@ matrix:
# fetch pre-built Linux protoc binaries in the test.
- os: linux
env: CONFIG=java_compatibility
# The Python compatibility test currently only runs on Linux because it will
# fetch pre-built Linux protoc binaries in the test.
- os: linux
env: CONFIG=python_compatibility
allow_failures:
# These currently do not work on OS X but are being worked on by @haberman.
- os: osx

View File

@ -0,0 +1,87 @@
#! /usr/bin/env python
#
import glob
import os
import subprocess
import sys
from setuptools import setup, Extension, find_packages
if sys.version_info[0] == 3:
# Python 3
from distutils.command.build_py import build_py_2to3 as _build_py
else:
# Python 2
from distutils.command.build_py import build_py as _build_py
from distutils.spawn import find_executable
def generate_proto(source, code_gen):
"""Invokes the Protocol Compiler to generate a _pb2.py from the given
.proto file."""
output = source.replace(".proto", "_pb2.py").replace("protos/src/proto/", "").replace("protos/python/", "")
if not os.path.exists(source):
sys.stderr.write("Can't find required file: %s\n" % source)
sys.exit(-1)
protoc_command = [ code_gen, "-Iprotos/src/proto", "-Iprotos/python", "--python_out=.", source ]
if subprocess.call(protoc_command) != 0:
sys.exit(-1)
class build_py(_build_py):
def run(self):
# generate .proto file
protoc_1 = "./protoc_1"
protoc_2 = "./protoc_2"
generate_proto("protos/src/proto/google/protobuf/unittest.proto", protoc_2)
generate_proto("protos/src/proto/google/protobuf/unittest_custom_options.proto", protoc_1)
generate_proto("protos/src/proto/google/protobuf/unittest_import.proto", protoc_1)
generate_proto("protos/src/proto/google/protobuf/unittest_import_public.proto", protoc_1)
generate_proto("protos/src/proto/google/protobuf/unittest_mset.proto", protoc_1)
generate_proto("protos/src/proto/google/protobuf/unittest_no_generic_services.proto", protoc_1)
generate_proto("protos/python/google/protobuf/internal/factory_test1.proto", protoc_1)
generate_proto("protos/python/google/protobuf/internal/factory_test2.proto", protoc_1)
generate_proto("protos/python/google/protobuf/internal/more_extensions.proto", protoc_1)
generate_proto("protos/python/google/protobuf/internal/more_extensions_dynamic.proto", protoc_1)
generate_proto("protos/python/google/protobuf/internal/more_messages.proto", protoc_1)
generate_proto("protos/python/google/protobuf/internal/test_bad_identifiers.proto", protoc_1)
# _build_py is an old-style class, so super() doesn't work.
_build_py.run(self)
if __name__ == '__main__':
# Keep this list of dependencies in sync with tox.ini.
install_requires = ['six>=1.9', 'setuptools']
if sys.version_info <= (2,7):
install_requires.append('ordereddict')
install_requires.append('unittest2')
setup(
name='protobuf',
description='Protocol Buffers',
download_url='https://github.com/google/protobuf/releases',
long_description="Protocol Buffers are Google's data interchange format",
url='https://developers.google.com/protocol-buffers/',
maintainer='protobuf@googlegroups.com',
maintainer_email='protobuf@googlegroups.com',
license='New BSD License',
classifiers=[
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
],
packages=find_packages(
exclude=[
'import_test_package',
],
),
test_suite='tests.google.protobuf.internal',
cmdclass={
'build_py': build_py,
},
install_requires=install_requires,
)

View File

@ -0,0 +1,110 @@
#!/bin/bash
set -ex
# Change to the script's directory.
cd $(dirname $0)
# Version of the tests (i.e., the version of protobuf from where we extracted
# these tests).
TEST_VERSION=2.5.0
# The old version of protobuf that we are testing compatibility against. This
# is usually the same as TEST_VERSION (i.e., we use the tests extracted from
# that version to test compatibility of the newest runtime against it), but it
# is also possible to use this same test set to test the compatibiilty of the
# latest version against other versions.
case "$1" in
""|2.5.0)
OLD_VERSION=2.5.0
OLD_VERSION_PROTOC=https://github.com/xfxyjwf/protobuf-compiler-release/raw/master/v2.5.0/linux/protoc
;;
2.6.1)
OLD_VERSION=2.6.1
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/2.6.1-build2/protoc-2.6.1-build2-linux-x86_64.exe
;;
3.0.0-beta-1)
OLD_VERSION=3.0.0-beta-1
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-1/protoc-3.0.0-beta-1-linux-x86_64.exe
;;
3.0.0-beta-2)
OLD_VERSION=3.0.0-beta-2
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-2/protoc-3.0.0-beta-2-linux-x86_64.exe
;;
3.0.0-beta-3)
OLD_VERSION=3.0.0-beta-3
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-3/protoc-3.0.0-beta-3-linux-x86_64.exe
;;
3.0.0-beta-4)
OLD_VERSION=3.0.0-beta-4
OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-4/protoc-3.0.0-beta-4-linux-x86_64.exe
;;
*)
echo "[ERROR]: Unknown version number: $1"
exit 1
;;
esac
# Extract the latest protobuf version number.
VERSION_NUMBER=`grep "^__version__ = '.*'" ../../google/protobuf/__init__.py | sed "s|__version__ = '\(.*\)'|\1|"`
echo "Running compatibility tests between $VERSION_NUMBER and $OLD_VERSION"
# Check protoc
[ -f ../../../src/protoc ] || {
echo "[ERROR]: Please build protoc first."
exit 1
}
# Test source compatibility. In these tests we recompile everything against
# the new runtime (including old version generated code).
rm google -f -r
mkdir -p google/protobuf/internal
# Build and copy the new runtime
cd ../../
python setup.py build
cp google/protobuf/*.py compatibility_tests/v2.5.0/google/protobuf/
cp google/protobuf/internal/*.py compatibility_tests/v2.5.0/google/protobuf/internal/
cd compatibility_tests/v2.5.0
cp tests/google/protobuf/internal/test_util.py google/protobuf/internal/
cp google/protobuf/__init__.py google/
# Download old version protoc compiler (for linux)
wget $OLD_VERSION_PROTOC -O old_protoc
chmod +x old_protoc
# Test A.1:
# proto set 1: use old version
# proto set 2 which may import protos in set 1: use old version
cp old_protoc protoc_1
cp old_protoc protoc_2
python setup.py build
python setup.py test
# Test A.2:
# proto set 1: use new version
# proto set 2 which may import protos in set 1: use old version
cp ../../../src/protoc protoc_1
cp old_protoc protoc_2
python setup.py build
python setup.py test
# Test A.3:
# proto set 1: use old version
# proto set 2 which may import protos in set 1: use new version
# Compatiblility test fail if the old verison is less than 3.0.0-alpha-1.
# Because module name aliases was added in v3.0.0-alpha-1 instead of
# fully-qualified module names to refer to dependencies: dot was replaced
# with _dot_.
if [ "$(printf "$OLD_VERSION\n3.0.0" | sort -V | head -n 1 )" = "3.0.0" ]; then
cp old_protoc protoc_1
cp ../../../src/protoc protoc_2
python setup.py build
python setup.py test
fi
rm google -r -f
rm build -r -f
rm protoc_1
rm protoc_2
rm old_protoc

View File

@ -567,9 +567,9 @@ def GoldenFile(filename):
# Search up the directory tree looking for the C++ protobuf source code.
path = '.'
while os.path.exists(path):
if os.path.exists(os.path.join(path, 'src/google/protobuf')):
if os.path.exists(os.path.join(path, 'tests/google/protobuf/internal')):
# Found it. Load the golden file from the testdata directory.
full_path = os.path.join(path, 'src/google/protobuf/testdata', filename)
full_path = os.path.join(path, 'tests/google/protobuf/internal', filename)
return open(full_path, 'rb')
path = os.path.join(path, '..')

View File

@ -94,6 +94,7 @@ class TextFormatTest(unittest.TestCase):
' }\n'
'}\n')
"""
def testPrintBadEnumValue(self):
message = unittest_pb2.TestAllTypes()
message.optional_nested_enum = 100
@ -115,6 +116,7 @@ class TextFormatTest(unittest.TestCase):
'[protobuf_unittest.optional_nested_enum_extension]: 100\n'
'[protobuf_unittest.optional_foreign_enum_extension]: 101\n'
'[protobuf_unittest.optional_import_enum_extension]: 102\n')
"""
def testPrintExotic(self):
message = unittest_pb2.TestAllTypes()
@ -470,7 +472,7 @@ class TextFormatTest(unittest.TestCase):
class TokenizerTest(unittest.TestCase):
"""
def testSimpleTokenCases(self):
text = ('identifier1:"string1"\n \n\n'
'identifier2 : \n \n123 \n identifier3 :\'string\'\n'
@ -585,6 +587,7 @@ class TokenizerTest(unittest.TestCase):
self.assertEqual(0, tokenizer.ConsumeUint32())
self.assertEqual(0, tokenizer.ConsumeUint64())
self.assertTrue(tokenizer.AtEnd())
"""
def testConsumeByteString(self):
text = '"string1\''

View File

@ -62,7 +62,8 @@ build_cpp_distcheck() {
# List all files that should be included in the distribution package.
git ls-files | grep "^\(java\|python\|objectivec\|csharp\|js\|ruby\|php\|cmake\|examples\)" |\
grep -v ".gitignore" | grep -v "java/compatibility_tests" > dist.lst
grep -v ".gitignore" | grep -v "java/compatibility_tests" |\
grep -v "python/compatibility_tests" > dist.lst
# Unzip the dist tar file.
DIST=`ls *.tar.gz`
tar -xf $DIST
@ -311,6 +312,16 @@ build_python_cpp() {
cd ..
}
build_python_compatibility() {
internal_build_cpp
# Use the unit-tests extraced from 2.5.0 to test the compatibilty.
cd python/compatibility_tests/v2.5.0
# Test between 2.5.0 and the current version.
./test.sh 2.5.0
# Test between 3.0.0-beta-1 and the current version.
./test.sh 3.0.0-beta-1
}
build_ruby21() {
internal_build_cpp # For conformance tests.
cd ruby && bash travis-test.sh ruby-2.1 && cd ..
@ -513,6 +524,7 @@ Usage: $0 { cpp |
objectivec_cocoapods_integration |
python |
python_cpp |
python_compatibility |
ruby21 |
ruby22 |
jruby |