Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2cdd5f7
fix: migrate parallel_upload.h and benchmarks to use unified checksum…
v-pratap Jul 24, 2026
eddcfdf
Completely remove deprecated legacy checksum options
v-pratap Jul 24, 2026
52f177f
Fix integration tests overlapping options, fix ReadObject using Uploa…
v-pratap Jul 25, 2026
67042df
storage: remove kCrc32cAndMD5 enum variant
v-pratap Jul 28, 2026
79e3883
Fix style guide violations and extract GetChecksumAlgorithm
v-pratap Jul 28, 2026
f008e43
Fix remaining styling issues and long lines
v-pratap Jul 28, 2026
6b3ca5f
Fix checksum_helpers_test compilation error due to removed structs
v-pratap Jul 28, 2026
5eab1c6
fix: resolve unused parameter warning in hash_validator.cc
v-pratap Jul 28, 2026
acfff2f
Update ABI dumps
v-pratap Jul 28, 2026
b9e74bb
fix(storage): consume server responses before finishing stream in Asy…
kalragauri Jul 28, 2026
a72ba49
chore(deps): update google-github-actions/auth action to v3 (#16268)
renovate-bot Jul 28, 2026
f07c472
build(cmake): update clang tidy property for NO_WARNINGS (#16281)
scotthart Jul 28, 2026
f8a0cac
feat(storage): add resource span attributes for ACO ( App Centric Obs…
bajajneha27 Jul 29, 2026
a3da4a0
Fix default tests for object hash and checksum
v-pratap Jul 29, 2026
92a3ed7
Format code properly
v-pratap Jul 29, 2026
83133b1
Merge upstream/main into remove-legacy-checksum-options
v-pratap Jul 29, 2026
e9270d1
fix: resolve parallel upload checksum dropping and throughput experim…
v-pratap Jul 29, 2026
abbad3c
style: clang-format fixes
v-pratap Jul 29, 2026
f12e48c
Update storage_grpc ABI dump
v-pratap Jul 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/macos-bazel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
ref: ${{ inputs.checkout-ref }}
persist-credentials: false
allow-unsafe-pr-checkout: true
- uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed # v2
- uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3
if: ${{ inputs.bazel-cache-mode == 'READ_WRITE' }}
with:
create_credentials_file: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/macos-cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
ref: ${{ inputs.checkout-ref }}
persist-credentials: false
allow-unsafe-pr-checkout: true
- uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed # v2
- uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3
if: ${{ inputs.sccache-mode == 'READ_WRITE' && inputs.vcpkg-cache-mode == 'readwrite' }}
with:
create_credentials_file: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows-bazel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
ref: ${{ inputs.checkout-ref }}
persist-credentials: false
allow-unsafe-pr-checkout: true
- uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed # v2
- uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3
if: ${{ inputs.bazel-cache-mode == 'READ_WRITE' }}
with:
create_credentials_file: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows-cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
ref: ${{ inputs.checkout-ref }}
persist-credentials: false
allow-unsafe-pr-checkout: true
- uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed # v2
- uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3
if: ${{ inputs.sccache-mode == 'READ_WRITE' && inputs.vcpkg-cache-mode == 'readwrite' }}
with:
create_credentials_file: true
Expand Down
Binary file modified ci/abi-dumps/google_cloud_cpp_storage.expected.abi.dump.gz
Binary file not shown.
Binary file modified ci/abi-dumps/google_cloud_cpp_storage_grpc.expected.abi.dump.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion cmake/GoogleCloudCppCommonOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ function (google_cloud_cpp_add_common_options target)
endif ()

if (_opt_NO_WARNINGS)
set_target_properties(${libname} PROPERTIES CXX_CLANG_TIDY "")
set_target_properties(${target} PROPERTIES CXX_CLANG_TIDY "")
return()
endif ()
if (GOOGLE_CLOUD_CPP_COMPILER_SUPPORTS_WALL)
Expand Down
35 changes: 23 additions & 12 deletions google/cloud/storage/benchmarks/throughput_experiment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ std::string ExtractUploadId(std::string v) {
return v.substr(pos + std::strlen(kRestField));
}

gcs::ChecksumAlgorithm GetChecksumAlgorithm(bool enable_crc32c,
bool enable_md5) {
if (enable_crc32c && enable_md5) {
throw std::invalid_argument(
"Cannot enable both CRC32C and MD5 checksum validation");
}
if (enable_crc32c) return gcs::ChecksumAlgorithm::kCrc32c;
if (enable_md5) return gcs::ChecksumAlgorithm::kMD5;
return gcs::ChecksumAlgorithm::kNone;
}

class ResumableUpload : public ThroughputExperiment {
public:
explicit ResumableUpload(google::cloud::storage::Client client,
Expand All @@ -80,10 +91,10 @@ class ResumableUpload : public ThroughputExperiment {

auto const start = std::chrono::system_clock::now();
auto timer = Timer::PerThread();
auto writer =
client_.WriteObject(bucket_name, object_name,
gcs::DisableCrc32cChecksum(!config.enable_crc32c),
gcs::DisableMD5Hash(!config.enable_md5));
auto writer = client_.WriteObject(
bucket_name, object_name,
google::cloud::Options{}.set<gcs::UploadChecksumValidationOption>(
GetChecksumAlgorithm(config.enable_crc32c, config.enable_md5)));
auto upload_id = ExtractUploadId(writer.resumable_session_id());
for (std::int64_t offset = 0; offset < config.object_size;
offset += config.app_buffer_size) {
Expand Down Expand Up @@ -151,10 +162,10 @@ class SimpleUpload : public ThroughputExperiment {
auto timer = Timer::PerThread();
auto data = absl::string_view{*random_data_}.substr(
0, static_cast<std::size_t>(config.object_size));
auto object_metadata =
client_.InsertObject(bucket_name, object_name, data,
gcs::DisableCrc32cChecksum(!config.enable_crc32c),
gcs::DisableMD5Hash(!config.enable_md5));
auto object_metadata = client_.InsertObject(
bucket_name, object_name, data,
google::cloud::Options{}.set<gcs::UploadChecksumValidationOption>(
GetChecksumAlgorithm(config.enable_crc32c, config.enable_md5)));
auto const usage = timer.Sample();
auto generation = object_metadata
? std::to_string(object_metadata->generation())
Expand Down Expand Up @@ -209,10 +220,10 @@ class DownloadObject : public ThroughputExperiment {
config.read_range.has_value()
? gcs::ReadRange(offset, offset + config.read_range->second)
: gcs::ReadRange();
auto reader =
client_.ReadObject(bucket_name, object_name, read_range,
gcs::DisableCrc32cChecksum(!config.enable_crc32c),
gcs::DisableMD5Hash(!config.enable_md5));
auto reader = client_.ReadObject(
bucket_name, object_name, read_range,
google::cloud::Options{}.set<gcs::DownloadChecksumValidationOption>(
GetChecksumAlgorithm(config.enable_crc32c, config.enable_md5)));
std::int64_t transfer_size = 0;
while (!reader.eof() && !reader.bad()) {
reader.read(buffer.data(), buffer.size());
Expand Down
14 changes: 7 additions & 7 deletions google/cloud/storage/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -946,8 +946,8 @@ class Client {
* @param contents the contents (media) for the new object.
* @param options a list of optional query parameters and/or request headers.
* Valid types for this operation include `ContentEncoding`,
* `ContentType`, `Crc32cChecksumValue`, `DisableCrc32cChecksum`,
* `DisableMD5Hash`, `EncryptionKey`, `IfGenerationMatch`,
* `ContentType`, `Crc32cChecksumValue`,
* `UploadChecksumValidationOption`, `EncryptionKey`, `IfGenerationMatch`,
* `IfGenerationNotMatch`, `IfMetagenerationMatch`,
* `IfMetagenerationNotMatch`, `KmsKeyName`, `MD5HashValue`,
* `PredefinedAcl`, `Projection`, `UserProject`, and `WithObjectMetadata`.
Expand Down Expand Up @@ -1176,9 +1176,9 @@ class Client {
* @param bucket_name the name of the bucket that contains the object.
* @param object_name the name of the object to be read.
* @param options a list of optional query parameters and/or request headers.
* Valid types for this operation include `DisableCrc32cChecksum`,
* `DisableMD5Hash`, `EncryptionKey`, `Generation`, `IfGenerationMatch`,
* `IfGenerationNotMatch`, `IfMetagenerationMatch`,
* Valid types for this operation include
* `DownloadChecksumValidationOption`, `EncryptionKey`, `Generation`,
* `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
* `IfMetagenerationNotMatch`, `ReadFromOffset`, `ReadRange`, `ReadLast`,
* `UserProject`, and `AcceptEncoding`.
*
Expand Down Expand Up @@ -1240,7 +1240,7 @@ class Client {
* @param object_name the name of the object to be read.
* @param options a list of optional query parameters and/or request headers.
* Valid types for this operation include `ContentEncoding`, `ContentType`,
* `Crc32cChecksumValue`, `DisableCrc32cChecksum`, `DisableMD5Hash`,
* `Crc32cChecksumValue`, `UploadChecksumValidationOption`,
* `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
* `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `KmsKeyName`,
* `MD5HashValue`, `PredefinedAcl`, `Projection`,
Expand Down Expand Up @@ -1295,7 +1295,7 @@ class Client {
* @param object_name the name of the object to be read.
* @param options a list of optional query parameters and/or request headers.
* Valid types for this operation include `ContentEncoding`, `ContentType`,
* `Crc32cChecksumValue`, `DisableCrc32cChecksum`, `DisableMD5Hash`,
* `Crc32cChecksumValue`, `UploadChecksumValidationOption`,
* `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
* `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `KmsKeyName`,
* `MD5HashValue`, `PredefinedAcl`, `Projection`, `UserProject`,
Expand Down
114 changes: 0 additions & 114 deletions google/cloud/storage/client_object_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -234,120 +234,6 @@ TEST_F(ObjectTest, ReadObject) {
EXPECT_EQ(actual.gcount(), 1024);
}

TEST_F(ObjectTest, ReadObjectChecksumPrecedence) {
EXPECT_CALL(*mock_, ReadObject)
.WillOnce([](internal::ReadObjectRangeRequest const& r) {
EXPECT_TRUE(r.HasOption<DisableMD5Hash>());
EXPECT_FALSE(r.GetOption<DisableMD5Hash>().value());

auto settings =
internal::GetDownloadChecksumSettings(r, CurrentOptions());
// Verify MD5 is enabled (disable_md5 = false) and CRC32C is disabled
// (disable_crc32c = true)
EXPECT_FALSE(settings.md5);
EXPECT_TRUE(settings.crc32c);

auto read_source = std::make_unique<testing::MockObjectReadSource>();
EXPECT_CALL(*read_source, IsOpen()).WillRepeatedly(Return(true));
EXPECT_CALL(*read_source, Read)
.WillOnce(Return(internal::ReadSourceResult{1024, {}}));
EXPECT_CALL(*read_source, Close).Times(1);
return StatusOr<std::unique_ptr<internal::ObjectReadSource>>(
std::move(read_source));
});
auto client = ClientForMock();
auto actual = client.ReadObject(
"test-bucket-name", "test-object-name", DisableMD5Hash(false),
Options{}.set<DownloadChecksumValidationOption>(
ChecksumAlgorithm::kNone));
ASSERT_STATUS_OK(actual.status());
std::vector<char> v(1024);
actual.read(v.data(), v.size());
EXPECT_EQ(actual.gcount(), 1024);
}

TEST_F(ObjectTest, ReadObjectChecksumPrecedenceDisableMD5) {
EXPECT_CALL(*mock_, ReadObject)
.WillOnce([](internal::ReadObjectRangeRequest const& r) {
EXPECT_TRUE(r.HasOption<DisableMD5Hash>());
EXPECT_TRUE(r.GetOption<DisableMD5Hash>().value());

auto settings =
internal::GetDownloadChecksumSettings(r, CurrentOptions());
// DisableMD5Hash(true) should override ChecksumAlgorithm::kMD5
EXPECT_TRUE(settings.md5);
EXPECT_TRUE(settings.crc32c); // kMD5 disables crc32c

auto read_source = std::make_unique<testing::MockObjectReadSource>();
EXPECT_CALL(*read_source, IsOpen()).WillRepeatedly(Return(true));
EXPECT_CALL(*read_source, Read)
.WillOnce(Return(internal::ReadSourceResult{1024, {}}));
EXPECT_CALL(*read_source, Close).Times(1);
return StatusOr<std::unique_ptr<internal::ObjectReadSource>>(
std::move(read_source));
});
auto client = ClientForMock();
auto actual = client.ReadObject(
"test-bucket-name", "test-object-name", DisableMD5Hash(true),
Options{}.set<DownloadChecksumValidationOption>(ChecksumAlgorithm::kMD5));
ASSERT_STATUS_OK(actual.status());
std::vector<char> v(1024);
actual.read(v.data(), v.size());
EXPECT_EQ(actual.gcount(), 1024);
}

TEST_F(ObjectTest, InsertObjectChecksumPrecedence) {
EXPECT_CALL(*mock_, InsertObjectMedia)
.WillOnce([](internal::InsertObjectMediaRequest const& r) {
EXPECT_TRUE(r.HasOption<DisableCrc32cChecksum>());
EXPECT_TRUE(r.GetOption<DisableCrc32cChecksum>().value());

auto settings =
internal::GetUploadChecksumSettings(r, CurrentOptions());
// Verify CRC32C is disabled (disable_crc32c = true) and MD5 remains
// enabled (disable_md5 = false)
EXPECT_TRUE(settings.crc32c);
EXPECT_FALSE(settings.md5);

return make_status_or(
storage::internal::ObjectMetadataParser::FromString(
R"({"name": "test-object-name"})")
.value());
});
auto client = ClientForMock();
auto actual =
client.InsertObject("test-bucket-name", "test-object-name", "payload",
DisableCrc32cChecksum(true),
Options{}.set<UploadChecksumValidationOption>(
ChecksumAlgorithm::kCrc32cAndMD5));
ASSERT_STATUS_OK(actual);
}

TEST_F(ObjectTest, InsertObjectChecksumPrecedenceEnableCrc32c) {
EXPECT_CALL(*mock_, InsertObjectMedia)
.WillOnce([](internal::InsertObjectMediaRequest const& r) {
EXPECT_TRUE(r.HasOption<DisableCrc32cChecksum>());
EXPECT_FALSE(r.GetOption<DisableCrc32cChecksum>().value());

auto settings =
internal::GetUploadChecksumSettings(r, CurrentOptions());
// DisableCrc32cChecksum(false) should override ChecksumAlgorithm::kNone
EXPECT_FALSE(settings.crc32c);
EXPECT_TRUE(settings.md5); // kNone disables md5

return make_status_or(
storage::internal::ObjectMetadataParser::FromString(
R"({"name": "test-object-name"})")
.value());
});
auto client = ClientForMock();
auto actual = client.InsertObject(
"test-bucket-name", "test-object-name", "payload",
DisableCrc32cChecksum(false),
Options{}.set<UploadChecksumValidationOption>(ChecksumAlgorithm::kNone));
ASSERT_STATUS_OK(actual);
}

TEST_F(ObjectTest, WriteObject) {
EXPECT_CALL(*mock_, CreateResumableUpload)
.WillOnce(Return(TransientError()))
Expand Down
61 changes: 0 additions & 61 deletions google/cloud/storage/hashing_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,40 +61,6 @@ inline std::string ComputeMD5Hash(char const* payload) {
: absl::string_view{payload});
}

/**
* Disable or enable MD5 Hashing computations.
*
* By default MD5 hashes are disabled. To enable them use the
* `EnableMD5Hash()` helper function.
*
* @warning MD5 hashes are disabled by default, as they are computationally
* expensive, and CRC32C checksums provide enough data integrity protection
* for most applications. Disabling CRC32C checksums while MD5 hashes remain
* disabled exposes your application to data corruption. We recommend that all
* uploads to GCS and downloads from GCS use CRC32C checksums.
*
* @deprecated Use `UploadChecksumValidationOption` and
* `DownloadChecksumValidationOption` instead.
*/
struct [[deprecated(
"Use UploadChecksumValidationOption and DownloadChecksumValidationOption "
"instead")]] DisableMD5Hash
: public internal::ComplexOption<DisableMD5Hash, bool> {
using ComplexOption<DisableMD5Hash, bool>::ComplexOption;
// GCC <= 7.0 does not use the inherited default constructor, redeclare it
// explicitly
DisableMD5Hash() = default;
static char const* name() { return "disable-md5-hash"; }
};

/**
* Enable MD5 hashes in upload and download operations.
*
* Use this function where the option `DisableMD5Hash` is expected to enable MD5
* hashes.
*/
inline DisableMD5Hash EnableMD5Hash() { return DisableMD5Hash(false); }

/**
* Provide a pre-computed CRC32C checksum value.
*
Expand Down Expand Up @@ -130,33 +96,6 @@ inline std::string ComputeCrc32cChecksum(char const* payload) {
: absl::string_view{payload});
}

/**
* Disable CRC32C checksum computations.
*
* By default the GCS client library computes CRC32C checksums in all upload and
* download operations. The application can use this option to disable the
* checksum computation.
*
* @warning MD5 hashes are disabled by default, as they are computationally
* expensive, and CRC32C checksums provide enough data integrity protection
* for most applications. Disabling CRC32C checksums while MD5 hashes remain
* disabled exposes your application to data corruption. We recommend that all
* uploads to GCS and downloads from GCS use CRC32C checksums.
*
* @deprecated Use `UploadChecksumValidationOption` and
* `DownloadChecksumValidationOption` instead.
*/
struct [[deprecated(
"Use UploadChecksumValidationOption and DownloadChecksumValidationOption "
"instead")]] DisableCrc32cChecksum
: public internal::ComplexOption<DisableCrc32cChecksum, bool> {
using ComplexOption<DisableCrc32cChecksum, bool>::ComplexOption;
// GCC <= 7.0 does not use the inherited default constructor, redeclare it
// explicitly
DisableCrc32cChecksum() = default;
static char const* name() { return "disable-crc32c-checksum"; }
};

GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
} // namespace storage
} // namespace cloud
Expand Down
Loading
Loading