From fa0b78a6c2ebc60f7d955e286812c40d76de23cb Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Tue, 25 Jun 2024 14:04:00 -0700 Subject: [PATCH] Add a warning for gencode that is one major version older than runtime PiperOrigin-RevId: 646598896 --- .../com/google/protobuf/RuntimeVersion.java | 28 ++++++++++++--- .../google/protobuf/RuntimeVersionTest.java | 35 +++++++++++++++++++ .../protobuf/internal/runtime_version_test.py | 29 +++++++++++++++ python/google/protobuf/runtime_version.py | 25 ++++++++++--- 4 files changed, 107 insertions(+), 10 deletions(-) diff --git a/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java b/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java index 6b4d57fc66127..b0f5e81a59dde 100644 --- a/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java +++ b/java/core/src/main/java/com/google/protobuf/RuntimeVersion.java @@ -7,6 +7,8 @@ package com.google.protobuf; +import java.util.logging.Logger; + /** * Provides the version of this Protobuf Java runtime, and methods for Protobuf Java gencode to * validate that versions are compatible. Fields and methods in this class should be only accessed @@ -36,6 +38,7 @@ public enum RuntimeDomain { public static final String SUFFIX = OSS_SUFFIX; private static final String VERSION_STRING = versionString(MAJOR, MINOR, PATCH, SUFFIX); + private static final Logger logger = Logger.getLogger(RuntimeVersion.class.getName()); /** * Validates that the gencode version is compatible with this runtime version according to @@ -83,11 +86,20 @@ private static void validateProtobufGencodeVersionImpl( // Check that runtime major version is the same as the gencode major version. if (major != MAJOR) { - throw new ProtobufRuntimeVersionException( - String.format( - "Detected mismatched Protobuf Gencode/Runtime major versions when loading %s: gencode" - + " %s, runtime %s. Same major version is required.", - location, gencodeVersionString, VERSION_STRING)); + if (major == MAJOR - 1) { + logger.warning( + String.format( + " Protobuf gencode version %s is exactly one major version older than the runtime" + + " version %s at %s. Please update the gencode to avoid compatibility" + + " violations in the next runtime release.", + gencodeVersionString, VERSION_STRING, location)); + } else { + throw new ProtobufRuntimeVersionException( + String.format( + "Detected mismatched Protobuf Gencode/Runtime major versions when loading %s:" + + " gencode %s, runtime %s. Same major version is required.", + location, gencodeVersionString, VERSION_STRING)); + } } // Check that runtime version is newer than the gencode version. @@ -97,6 +109,12 @@ private static void validateProtobufGencodeVersionImpl( "Detected incompatible Protobuf Gencode/Runtime versions when loading %s: gencode %s," + " runtime %s. Runtime version cannot be older than the linked gencode version.", location, gencodeVersionString, VERSION_STRING)); + } else if (MINOR > minor || PATCH > patch) { + logger.warning( + String.format( + " Protobuf gencode version %s is older than the runtime version %s at %s. Please" + + " avoid checked-in Protobuf gencode that can be obsolete.", + gencodeVersionString, VERSION_STRING, location)); } // Check that runtime version suffix is the same as the gencode version suffix. diff --git a/java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java b/java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java index ce28f9eea09bc..e2fae7d219321 100644 --- a/java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java +++ b/java/core/src/test/java/com/google/protobuf/RuntimeVersionTest.java @@ -10,6 +10,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import java.util.logging.Logger; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -144,4 +145,38 @@ public void versionValidation_differentVesionSuffixDisallowed() { "Detected mismatched Protobuf Gencode/Runtime version suffixes when loading" + " testing.Foo"); } + + @Test + public void versionValidation_warnOlderGencodeVersion() { + TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler(); + Logger logger = Logger.getLogger(RuntimeVersion.class.getName()); + logger.addHandler(logHandler); + RuntimeVersion.validateProtobufGencodeVersion( + RuntimeVersion.DOMAIN, + RuntimeVersion.MAJOR, + RuntimeVersion.MINOR - 1, + RuntimeVersion.PATCH, + RuntimeVersion.SUFFIX, + "dummy"); + assertThat(logHandler.getStoredLogRecords()).hasSize(1); + assertThat(logHandler.getStoredLogRecords().get(0).getMessage()) + .contains("Please avoid checked-in Protobuf gencode that can be obsolete."); + } + + @Test + public void versionValidation_gencodeOneMajorVersionOlderWarning() { + TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler(); + Logger logger = Logger.getLogger(RuntimeVersion.class.getName()); + logger.addHandler(logHandler); + RuntimeVersion.validateProtobufGencodeVersion( + RuntimeVersion.DOMAIN, + RuntimeVersion.MAJOR - 1, + RuntimeVersion.MINOR, + RuntimeVersion.PATCH, + RuntimeVersion.SUFFIX, + "dummy"); + assertThat(logHandler.getStoredLogRecords()).hasSize(1); + assertThat(logHandler.getStoredLogRecords().get(0).getMessage()) + .contains("is exactly one major version older than the runtime version"); + } } diff --git a/python/google/protobuf/internal/runtime_version_test.py b/python/google/protobuf/internal/runtime_version_test.py index 8608bd2626345..fcede1430a5a8 100644 --- a/python/google/protobuf/internal/runtime_version_test.py +++ b/python/google/protobuf/internal/runtime_version_test.py @@ -118,6 +118,35 @@ def test_different_suffix_disallowed(self): 'foo.proto', ) + def test_gencode_older_than_runtime_version_warning(self): + with self.assertWarnsRegex( + Warning, + expected_regex=( + 'Please avoid checked-in Protobuf gencode that can be obsolete.' + ), + ): + runtime_version.ValidateProtobufRuntimeVersion( + runtime_version.DOMAIN, + runtime_version.MAJOR, + runtime_version.MINOR - 1, + runtime_version.PATCH, + runtime_version.SUFFIX, + 'foo.proto', + ) + + def test_gencode_one_major_version_older_warning(self): + with self.assertWarnsRegex( + Warning, expected_regex='is exactly one major version older' + ): + runtime_version.ValidateProtobufRuntimeVersion( + runtime_version.DOMAIN, + runtime_version.MAJOR - 1, + runtime_version.MINOR, + runtime_version.PATCH, + runtime_version.SUFFIX, + 'foo.proto', + ) + if __name__ == '__main__': unittest.main() diff --git a/python/google/protobuf/runtime_version.py b/python/google/protobuf/runtime_version.py index 7f294b36fb943..d8325fb71b25b 100644 --- a/python/google/protobuf/runtime_version.py +++ b/python/google/protobuf/runtime_version.py @@ -15,6 +15,7 @@ from enum import Enum import os +import warnings class Domain(Enum): @@ -87,11 +88,19 @@ def ValidateProtobufRuntimeVersion( ) if gen_major != MAJOR: - _ReportVersionError( - 'Detected mismatched Protobuf Gencode/Runtime major versions when' - f' loading {location}: gencode {gen_version} runtime {version}.' - f' Same major version is required. {error_prompt}' - ) + if gen_major == MAJOR - 1: + warnings.warn( + 'Protobuf gencode version %s is exactly one major version older than' + ' the runtime version %s at %s. Please update the gencode to avoid' + ' compatibility violations in the next runtime release.' + % (gen_version, version, location) + ) + else: + _ReportVersionError( + 'Detected mismatched Protobuf Gencode/Runtime major versions when' + f' loading {location}: gencode {gen_version} runtime {version}.' + f' Same major version is required. {error_prompt}' + ) if MINOR < gen_minor or (MINOR == gen_minor and PATCH < gen_patch): _ReportVersionError( @@ -99,6 +108,12 @@ def ValidateProtobufRuntimeVersion( f' {location}: gencode {gen_version} runtime {version}. Runtime version' f' cannot be older than the linked gencode version. {error_prompt}' ) + elif MINOR > gen_minor or PATCH > gen_patch: + warnings.warn( + 'Protobuf gencode version %s is older than the runtime version %s at' + ' %s. Please avoid checked-in Protobuf gencode that can be obsolete.' + % (gen_version, version, location) + ) if gen_suffix != SUFFIX: _ReportVersionError(