From ef253aa1430e1d966f5050b841f518dea3e76f7b Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Wed, 30 Apr 2025 13:24:20 +0000 Subject: [PATCH 1/9] add samples and test cases for soft delete objects --- .../ListSoftDeletedObjectsTest.cs | 49 ++++++++++++++++ .../ListSoftDeletedVersionsOfObjectTest.cs | 58 +++++++++++++++++++ .../RestoreSoftDeletedObjectTest.cs | 45 ++++++++++++++ .../Storage.Samples.Tests/StorageFixture.cs | 4 ++ .../Storage.Samples/ListSoftDeletedObjects.cs | 39 +++++++++++++ .../ListSoftDeletedVersionsOfObject.cs | 41 +++++++++++++ .../RestoreSoftDeletedObject.cs | 39 +++++++++++++ 7 files changed, 275 insertions(+) create mode 100644 storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs create mode 100644 storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs create mode 100644 storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs create mode 100644 storage/api/Storage.Samples/ListSoftDeletedObjects.cs create mode 100644 storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs create mode 100644 storage/api/Storage.Samples/RestoreSoftDeletedObject.cs diff --git a/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs b/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs new file mode 100644 index 00000000000..4b37bd64e81 --- /dev/null +++ b/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs @@ -0,0 +1,49 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Xunit; + +[Collection(nameof(StorageFixture))] +public class ListSoftDeletedObjectsTest +{ + private readonly StorageFixture _fixture; + + public ListSoftDeletedObjectsTest(StorageFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public void ListSoftDeletedObjects() + { + ListSoftDeletedObjectsSample listSoftDeletedObjects = new ListSoftDeletedObjectsSample(); + UploadObjectFromMemorySample uploadObjectFromMemory = new UploadObjectFromMemorySample(); + var bucketName = _fixture.GenerateBucketName(); + _fixture.CreateBucket(bucketName, multiVersion: false, softDelete: false, registerForDeletion: true); + var objectNameOne = _fixture.GenerateName(); + var objectOneContent = _fixture.GenerateContent(); + var objectNameTwo = _fixture.GenerateName(); + var objectTwoContent = _fixture.GenerateContent(); + uploadObjectFromMemory.UploadObjectFromMemory(bucketName, objectNameOne, objectOneContent); + uploadObjectFromMemory.UploadObjectFromMemory(bucketName, objectNameTwo, objectTwoContent); + _fixture.Client.DeleteObject(bucketName, objectNameOne); + _fixture.Client.DeleteObject(bucketName, objectNameTwo); + var objects = listSoftDeletedObjects.ListSoftDeletedObjects(bucketName); + Assert.Multiple( + () => Assert.Contains(objects, obj => obj.Name == objectNameOne), + () => Assert.Contains(objects, obj => obj.Name == objectNameTwo) + ); + } +} diff --git a/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs b/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs new file mode 100644 index 00000000000..b68dcc9fcc2 --- /dev/null +++ b/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs @@ -0,0 +1,58 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using Xunit; + +[Collection(nameof(StorageFixture))] +public class ListSoftDeletedVersionOfObjectTest +{ + private readonly StorageFixture _fixture; + private IList _softDeleteObjectGenerations { get; } = new List(); + + public ListSoftDeletedVersionOfObjectTest(StorageFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public void ListSoftDeletedVersionOfObject() + { + int i = 2; + ListSoftDeletedVersionOfObjectSample listSoftDeletedVersionOfObject = new ListSoftDeletedVersionOfObjectSample(); + UploadObjectFromMemorySample uploadObjectFromMemory = new UploadObjectFromMemorySample(); + RestoreSoftDeletedObjectSample restoreSoftDeletedObjectSample = new RestoreSoftDeletedObjectSample(); + GetMetadataSample getMetadataSample = new GetMetadataSample(); + var bucketName = _fixture.GenerateBucketName(); + _fixture.CreateBucket(bucketName, multiVersion: false, softDelete: false, registerForDeletion: true); + var objectName = _fixture.GenerateName(); + var objectContent = _fixture.GenerateContent(); + uploadObjectFromMemory.UploadObjectFromMemory(bucketName, objectName, objectContent); + while (i >= 0) + { + var objectMetaData = getMetadataSample.GetMetadata(bucketName, objectName); + _softDeleteObjectGenerations.Add(objectMetaData.Generation.Value); + _fixture.Client.DeleteObject(bucketName, objectName); + var restoredObject = restoreSoftDeletedObjectSample.RestoreSoftDeletedObject(bucketName, objectName, objectMetaData.Generation.Value); + i--; + } + var objects = listSoftDeletedVersionOfObject.ListSoftDeletedVersionOfObject(bucketName, objectName); + Assert.Multiple( + () => Assert.Contains(objects, obj => obj.Name == objectName && obj.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 1]), + () => Assert.Contains(objects, obj => obj.Name == objectName && obj.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 2]), + () => Assert.Contains(objects, obj => obj.Name == objectName && obj.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 3]) + ); + _fixture.Client.DeleteObject(bucketName, objectName); + } +} diff --git a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs new file mode 100644 index 00000000000..2635061f977 --- /dev/null +++ b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs @@ -0,0 +1,45 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Xunit; + +[Collection(nameof(StorageFixture))] +public class RestoreSoftDeletedObjectTest +{ + private readonly StorageFixture _fixture; + + public RestoreSoftDeletedObjectTest(StorageFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public void RestoreSoftDeletedObject() + { + RestoreSoftDeletedObjectSample restoreSoftDeletedObjectSample = new RestoreSoftDeletedObjectSample(); + UploadObjectFromMemorySample uploadObjectFromMemory = new UploadObjectFromMemorySample(); + GetMetadataSample getMetadataSample = new GetMetadataSample(); + var bucketName = _fixture.GenerateBucketName(); + _fixture.CreateBucket(bucketName, multiVersion: false, softDelete: true, registerForDeletion: true); + var objectName = _fixture.GenerateName(); + var objectContent = _fixture.GenerateContent(); + uploadObjectFromMemory.UploadObjectFromMemory(bucketName, objectName, objectContent); + var objectMetaData = getMetadataSample.GetMetadata(bucketName, objectName); + _fixture.Client.DeleteObject(bucketName, objectName); + var restoredObject = restoreSoftDeletedObjectSample.RestoreSoftDeletedObject(bucketName, objectName, objectMetaData.Generation.Value); + Assert.Equal(objectName, restoredObject.Name); + _fixture.Client.DeleteObject(bucketName, objectName); + } +} diff --git a/storage/api/Storage.Samples.Tests/StorageFixture.cs b/storage/api/Storage.Samples.Tests/StorageFixture.cs index 9bcc2903b58..6161e7efe4f 100644 --- a/storage/api/Storage.Samples.Tests/StorageFixture.cs +++ b/storage/api/Storage.Samples.Tests/StorageFixture.cs @@ -239,6 +239,10 @@ internal Bucket CreateBucket(string name, bool multiVersion, bool softDelete = f internal string GenerateBucketName() => Guid.NewGuid().ToString(); + internal string GenerateName() => Guid.NewGuid().ToString(); + + internal string GenerateContent() => Guid.NewGuid().ToString(); + /// /// Bucket creation/update/deletion is rate-limited. To avoid making the tests flaky, we sleep after each operation. /// diff --git a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs new file mode 100644 index 00000000000..8e3e6b9b133 --- /dev/null +++ b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs @@ -0,0 +1,39 @@ +// Copyright 2025 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// [START storage_list_soft_deleted_objects] + +using Google.Cloud.Storage.V1; +using System; +using System.Collections.Generic; + +public class ListSoftDeletedObjectsSample +{ + /// + /// List soft deleted objects. + /// + /// The name of the bucket. + public IEnumerable ListSoftDeletedObjects(string bucketName = "your-unique-bucket-name") + { + var storage = StorageClient.Create(); + var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true }); + Console.WriteLine("Soft Deleted Objects are as follows:"); + foreach (var obj in objects) + { + Console.WriteLine($"Name: {obj.Name}"); + } + return objects; + } +} +// [END storage_list_soft_deleted_objects] diff --git a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs new file mode 100644 index 00000000000..4dd25f8ab93 --- /dev/null +++ b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs @@ -0,0 +1,41 @@ +// Copyright 2025 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// [START storage_list_soft_deleted_object_versions] + +using Google.Cloud.Storage.V1; +using System; +using System.Collections.Generic; + +public class ListSoftDeletedVersionOfObjectSample +{ + /// + /// List soft deleted versions of the object. + /// + /// The name of the bucket. + /// The name of the soft-deleted object. + public IEnumerable ListSoftDeletedVersionOfObject(string bucketName = "your-unique-bucket-name", + string objectName = "your-object-name") + { + var storage = StorageClient.Create(); + var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true, MatchGlob = objectName }); + Console.WriteLine("Soft Deleted Versions of the Object with the Name and Versions are as follows:"); + foreach (var obj in objects) + { + Console.WriteLine($"Name: {obj.Name} and Version : {obj.Generation}"); + } + return objects; + } +} +// [END storage_list_soft_deleted_object_versions] diff --git a/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs b/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs new file mode 100644 index 00000000000..a58bd629493 --- /dev/null +++ b/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs @@ -0,0 +1,39 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"). +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// [START storage_restore_object] + +using Google.Cloud.Storage.V1; +using System; + +public class RestoreSoftDeletedObjectSample +{ + /// + /// Restores a soft deleted object. + /// + /// The name of the bucket. + /// The name of the soft-deleted object to restore. + /// The generation number of the soft-deleted object to restore. + public Google.Apis.Storage.v1.Data.Object RestoreSoftDeletedObject( + string bucketName = "your-unique-bucket-name", + string objectName = "your-object-name", + long generation = 1579287380533984) + { + var client = StorageClient.Create(); + var restoredObject = client.RestoreObject(bucketName, objectName, generation); + Console.WriteLine($"The Name of the Restored Previously Soft-deleted Object is : {restoredObject.Name}"); + return restoredObject; + } +} +// [END storage_restore_object] From e0e4474204c6db9d9a0507bf41df6d4a19e2b559 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Fri, 2 May 2025 05:58:26 -0700 Subject: [PATCH 2/9] sample and test case changes for soft delete object --- .../ListSoftDeletedObjectsTest.cs | 1 - .../ListSoftDeletedVersionsOfObjectTest.cs | 4 ++-- .../RestoreSoftDeletedObjectTest.cs | 1 - storage/api/Storage.Samples/ListSoftDeletedObjects.cs | 4 ++-- .../Storage.Samples/ListSoftDeletedVersionsOfObject.cs | 10 +++++----- .../api/Storage.Samples/RestoreSoftDeletedObject.cs | 4 ++-- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs b/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs index 4b37bd64e81..71c5f7b70b1 100644 --- a/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs +++ b/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using Xunit; [Collection(nameof(StorageFixture))] diff --git a/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs b/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs index b68dcc9fcc2..669cf8a4000 100644 --- a/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs +++ b/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs @@ -30,7 +30,7 @@ public ListSoftDeletedVersionOfObjectTest(StorageFixture fixture) public void ListSoftDeletedVersionOfObject() { int i = 2; - ListSoftDeletedVersionOfObjectSample listSoftDeletedVersionOfObject = new ListSoftDeletedVersionOfObjectSample(); + ListSoftDeletedVersionsOfObjectSample listSoftDeletedVersionOfObject = new ListSoftDeletedVersionsOfObjectSample(); UploadObjectFromMemorySample uploadObjectFromMemory = new UploadObjectFromMemorySample(); RestoreSoftDeletedObjectSample restoreSoftDeletedObjectSample = new RestoreSoftDeletedObjectSample(); GetMetadataSample getMetadataSample = new GetMetadataSample(); @@ -47,7 +47,7 @@ public void ListSoftDeletedVersionOfObject() var restoredObject = restoreSoftDeletedObjectSample.RestoreSoftDeletedObject(bucketName, objectName, objectMetaData.Generation.Value); i--; } - var objects = listSoftDeletedVersionOfObject.ListSoftDeletedVersionOfObject(bucketName, objectName); + var objects = listSoftDeletedVersionOfObject.ListSoftDeletedVersionsOfObject(bucketName, objectName); Assert.Multiple( () => Assert.Contains(objects, obj => obj.Name == objectName && obj.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 1]), () => Assert.Contains(objects, obj => obj.Name == objectName && obj.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 2]), diff --git a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs index 2635061f977..7b1b6836985 100644 --- a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs +++ b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using Xunit; [Collection(nameof(StorageFixture))] diff --git a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs index 8e3e6b9b133..99a459c193a 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs @@ -21,14 +21,14 @@ public class ListSoftDeletedObjectsSample { /// - /// List soft deleted objects. + /// List all of the soft-deleted objects in a bucket. /// /// The name of the bucket. public IEnumerable ListSoftDeletedObjects(string bucketName = "your-unique-bucket-name") { var storage = StorageClient.Create(); var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true }); - Console.WriteLine("Soft Deleted Objects are as follows:"); + Console.WriteLine("Soft Deleted Objects with the Name are as follows:"); foreach (var obj in objects) { Console.WriteLine($"Name: {obj.Name}"); diff --git a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs index 4dd25f8ab93..6bf7b1353e8 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs @@ -18,14 +18,14 @@ using System; using System.Collections.Generic; -public class ListSoftDeletedVersionOfObjectSample +public class ListSoftDeletedVersionsOfObjectSample { /// - /// List soft deleted versions of the object. + /// List all soft-deleted versions of the object in a bucket. /// /// The name of the bucket. - /// The name of the soft-deleted object. - public IEnumerable ListSoftDeletedVersionOfObject(string bucketName = "your-unique-bucket-name", + /// The name of the object. + public IEnumerable ListSoftDeletedVersionsOfObject(string bucketName = "your-unique-bucket-name", string objectName = "your-object-name") { var storage = StorageClient.Create(); @@ -33,7 +33,7 @@ public class ListSoftDeletedVersionOfObjectSample Console.WriteLine("Soft Deleted Versions of the Object with the Name and Versions are as follows:"); foreach (var obj in objects) { - Console.WriteLine($"Name: {obj.Name} and Version : {obj.Generation}"); + Console.WriteLine($"Name: {obj.Name} and Version: {obj.Generation}"); } return objects; } diff --git a/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs b/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs index a58bd629493..e9f79f8cf95 100644 --- a/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs +++ b/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs @@ -20,11 +20,11 @@ public class RestoreSoftDeletedObjectSample { /// - /// Restores a soft deleted object. + /// Restores a soft-deleted object. /// /// The name of the bucket. /// The name of the soft-deleted object to restore. - /// The generation number of the soft-deleted object to restore. + /// The generation of the soft-deleted object to restore. public Google.Apis.Storage.v1.Data.Object RestoreSoftDeletedObject( string bucketName = "your-unique-bucket-name", string objectName = "your-object-name", From 44d3790f71dbf38884678c8611ef48d84d3a5179 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Fri, 2 May 2025 06:07:20 -0700 Subject: [PATCH 3/9] minor changes --- .../ListSoftDeletedVersionsOfObjectTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs b/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs index 669cf8a4000..56af497f072 100644 --- a/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs +++ b/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs @@ -16,18 +16,18 @@ using Xunit; [Collection(nameof(StorageFixture))] -public class ListSoftDeletedVersionOfObjectTest +public class ListSoftDeletedVersionsOfObjectTest { private readonly StorageFixture _fixture; private IList _softDeleteObjectGenerations { get; } = new List(); - public ListSoftDeletedVersionOfObjectTest(StorageFixture fixture) + public ListSoftDeletedVersionsOfObjectTest(StorageFixture fixture) { _fixture = fixture; } [Fact] - public void ListSoftDeletedVersionOfObject() + public void ListSoftDeletedVersionsOfObject() { int i = 2; ListSoftDeletedVersionsOfObjectSample listSoftDeletedVersionOfObject = new ListSoftDeletedVersionsOfObjectSample(); From 8050ed2e04242356197708340a620952e4e6ee85 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Mon, 5 May 2025 04:07:33 -0700 Subject: [PATCH 4/9] samples and tests changes --- .../ListSoftDeletedObjectsTest.cs | 21 +++++++++++++--- .../ListSoftDeletedVersionsOfObjectTest.cs | 25 ++++++++++++++----- .../RestoreSoftDeletedObjectTest.cs | 1 + .../Storage.Samples/ListSoftDeletedObjects.cs | 6 ++--- .../ListSoftDeletedVersionsOfObject.cs | 6 ++--- .../RestoreSoftDeletedObject.cs | 6 ++--- 6 files changed, 47 insertions(+), 18 deletions(-) diff --git a/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs b/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs index 71c5f7b70b1..372c7c9cc81 100644 --- a/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs +++ b/storage/api/Storage.Samples.Tests/ListSoftDeletedObjectsTest.cs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using Google.Apis.Storage.v1.Data; +using System.Linq; using Xunit; [Collection(nameof(StorageFixture))] @@ -37,12 +39,25 @@ public void ListSoftDeletedObjects() var objectTwoContent = _fixture.GenerateContent(); uploadObjectFromMemory.UploadObjectFromMemory(bucketName, objectNameOne, objectOneContent); uploadObjectFromMemory.UploadObjectFromMemory(bucketName, objectNameTwo, objectTwoContent); + var preSoftDeleteObjects = _fixture.Client.ListObjects(bucketName); + int preSoftDeleteObjectsCount = preSoftDeleteObjects.Count(); _fixture.Client.DeleteObject(bucketName, objectNameOne); _fixture.Client.DeleteObject(bucketName, objectNameTwo); - var objects = listSoftDeletedObjects.ListSoftDeletedObjects(bucketName); + var softDeletedObjects = listSoftDeletedObjects.ListSoftDeletedObjects(bucketName); + int softDeletedObjectsCount = softDeletedObjects.Count(); + Assert.Equal(preSoftDeleteObjectsCount, softDeletedObjectsCount); + Assert.All(softDeletedObjects, AssertSoftDeletedObject); Assert.Multiple( - () => Assert.Contains(objects, obj => obj.Name == objectNameOne), - () => Assert.Contains(objects, obj => obj.Name == objectNameTwo) + () => Assert.Contains(softDeletedObjects, softDeletedObject => softDeletedObject.Name == objectNameOne), + () => Assert.Contains(softDeletedObjects, softDeletedObject => softDeletedObject.Name == objectNameTwo) ); } + + // Validates that the given object is soft-deleted. + private void AssertSoftDeletedObject(Object o) + { + Assert.NotNull(o.Generation); + Assert.NotNull(o.HardDeleteTimeDateTimeOffset); + Assert.NotNull(o.SoftDeleteTimeDateTimeOffset); + } } diff --git a/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs b/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs index 56af497f072..17f4b168a2f 100644 --- a/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs +++ b/storage/api/Storage.Samples.Tests/ListSoftDeletedVersionsOfObjectTest.cs @@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +using Google.Apis.Storage.v1.Data; using System.Collections.Generic; +using System.Linq; using Xunit; [Collection(nameof(StorageFixture))] @@ -29,7 +31,8 @@ public ListSoftDeletedVersionsOfObjectTest(StorageFixture fixture) [Fact] public void ListSoftDeletedVersionsOfObject() { - int i = 2; + int i = 3; + int preSoftDeleteObjectVersionsCount = i; ListSoftDeletedVersionsOfObjectSample listSoftDeletedVersionOfObject = new ListSoftDeletedVersionsOfObjectSample(); UploadObjectFromMemorySample uploadObjectFromMemory = new UploadObjectFromMemorySample(); RestoreSoftDeletedObjectSample restoreSoftDeletedObjectSample = new RestoreSoftDeletedObjectSample(); @@ -39,7 +42,7 @@ public void ListSoftDeletedVersionsOfObject() var objectName = _fixture.GenerateName(); var objectContent = _fixture.GenerateContent(); uploadObjectFromMemory.UploadObjectFromMemory(bucketName, objectName, objectContent); - while (i >= 0) + while (i >= 1) { var objectMetaData = getMetadataSample.GetMetadata(bucketName, objectName); _softDeleteObjectGenerations.Add(objectMetaData.Generation.Value); @@ -47,12 +50,22 @@ public void ListSoftDeletedVersionsOfObject() var restoredObject = restoreSoftDeletedObjectSample.RestoreSoftDeletedObject(bucketName, objectName, objectMetaData.Generation.Value); i--; } - var objects = listSoftDeletedVersionOfObject.ListSoftDeletedVersionsOfObject(bucketName, objectName); + var softDeletedObjectVersions = listSoftDeletedVersionOfObject.ListSoftDeletedVersionsOfObject(bucketName, objectName); + int softDeletedObjectVersionsCount = softDeletedObjectVersions.Count(); + Assert.Equal(preSoftDeleteObjectVersionsCount, softDeletedObjectVersionsCount); + Assert.All(softDeletedObjectVersions, AssertSoftDeletedVersionsOfObject); Assert.Multiple( - () => Assert.Contains(objects, obj => obj.Name == objectName && obj.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 1]), - () => Assert.Contains(objects, obj => obj.Name == objectName && obj.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 2]), - () => Assert.Contains(objects, obj => obj.Name == objectName && obj.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 3]) + () => Assert.Contains(softDeletedObjectVersions, softDeletedObject => softDeletedObject.Name == objectName && softDeletedObject.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 1]), + () => Assert.Contains(softDeletedObjectVersions, softDeletedObject => softDeletedObject.Name == objectName && softDeletedObject.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 2]), + () => Assert.Contains(softDeletedObjectVersions, softDeletedObject => softDeletedObject.Name == objectName && softDeletedObject.Generation == _softDeleteObjectGenerations[_softDeleteObjectGenerations.Count - 3]) ); _fixture.Client.DeleteObject(bucketName, objectName); } + + private void AssertSoftDeletedVersionsOfObject(Object o) + { + Assert.NotNull(o.Generation); + Assert.NotNull(o.HardDeleteTimeDateTimeOffset); + Assert.NotNull(o.SoftDeleteTimeDateTimeOffset); + } } diff --git a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs index 7b1b6836985..5c4476dac1c 100644 --- a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs +++ b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs @@ -39,6 +39,7 @@ public void RestoreSoftDeletedObject() _fixture.Client.DeleteObject(bucketName, objectName); var restoredObject = restoreSoftDeletedObjectSample.RestoreSoftDeletedObject(bucketName, objectName, objectMetaData.Generation.Value); Assert.Equal(objectName, restoredObject.Name); + Assert.Equal(objectMetaData.Size, restoredObject.Size); _fixture.Client.DeleteObject(bucketName, objectName); } } diff --git a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs index 99a459c193a..40ad6870ff4 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs @@ -21,17 +21,17 @@ public class ListSoftDeletedObjectsSample { /// - /// List all of the soft-deleted objects in a bucket. + /// List all soft-deleted objects in the bucket. /// /// The name of the bucket. public IEnumerable ListSoftDeletedObjects(string bucketName = "your-unique-bucket-name") { var storage = StorageClient.Create(); var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true }); - Console.WriteLine("Soft Deleted Objects with the Name are as follows:"); + Console.WriteLine($"Soft Deleted Objects in the {bucketName}, identified by their respective Names are as follows:"); foreach (var obj in objects) { - Console.WriteLine($"Name: {obj.Name}"); + Console.WriteLine($"Object Name: {obj.Name}"); } return objects; } diff --git a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs index 6bf7b1353e8..fc06f447fc4 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs @@ -21,7 +21,7 @@ public class ListSoftDeletedVersionsOfObjectSample { /// - /// List all soft-deleted versions of the object in a bucket. + /// List all soft-deleted versions of the object in the bucket. /// /// The name of the bucket. /// The name of the object. @@ -30,10 +30,10 @@ public class ListSoftDeletedVersionsOfObjectSample { var storage = StorageClient.Create(); var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true, MatchGlob = objectName }); - Console.WriteLine("Soft Deleted Versions of the Object with the Name and Versions are as follows:"); + Console.WriteLine($"Soft Deleted Versions of the Object exist in the {bucketName}, identified by their respective Names and Versions are as follows:"); foreach (var obj in objects) { - Console.WriteLine($"Name: {obj.Name} and Version: {obj.Generation}"); + Console.WriteLine($"Object Name: {obj.Name} and Version: {obj.Generation}"); } return objects; } diff --git a/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs b/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs index e9f79f8cf95..41ffe85125a 100644 --- a/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs +++ b/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs @@ -23,8 +23,8 @@ public class RestoreSoftDeletedObjectSample /// Restores a soft-deleted object. /// /// The name of the bucket. - /// The name of the soft-deleted object to restore. - /// The generation of the soft-deleted object to restore. + /// The name of the soft-deleted object. + /// The generation of the soft-deleted object. public Google.Apis.Storage.v1.Data.Object RestoreSoftDeletedObject( string bucketName = "your-unique-bucket-name", string objectName = "your-object-name", @@ -32,7 +32,7 @@ public Google.Apis.Storage.v1.Data.Object RestoreSoftDeletedObject( { var client = StorageClient.Create(); var restoredObject = client.RestoreObject(bucketName, objectName, generation); - Console.WriteLine($"The Name of the Restored Previously Soft-deleted Object is : {restoredObject.Name}"); + Console.WriteLine($"The Name of the Restored Object after being previously soft deleted is : {restoredObject.Name}"); return restoredObject; } } From a0ee44895494eed80469c46f804bbee28a568c02 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Tue, 6 May 2025 02:50:09 -0700 Subject: [PATCH 5/9] Rewording of console output --- .../api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs | 1 + storage/api/Storage.Samples/ListSoftDeletedObjects.cs | 2 +- storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs | 2 +- storage/api/Storage.Samples/RestoreSoftDeletedObject.cs | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs index 5c4476dac1c..36fee8713fd 100644 --- a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs +++ b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs @@ -40,6 +40,7 @@ public void RestoreSoftDeletedObject() var restoredObject = restoreSoftDeletedObjectSample.RestoreSoftDeletedObject(bucketName, objectName, objectMetaData.Generation.Value); Assert.Equal(objectName, restoredObject.Name); Assert.Equal(objectMetaData.Size, restoredObject.Size); + Assert.Equal(objectMetaData.Md5Hash, restoredObject.Md5Hash); _fixture.Client.DeleteObject(bucketName, objectName); } } diff --git a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs index 40ad6870ff4..d805c0ee082 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs @@ -28,7 +28,7 @@ public class ListSoftDeletedObjectsSample { var storage = StorageClient.Create(); var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true }); - Console.WriteLine($"Soft Deleted Objects in the {bucketName}, identified by their respective Names are as follows:"); + Console.WriteLine($"Names of the Soft Deleted Objects in the Bucket (Bucket Name: {bucketName}) are as follows:"); foreach (var obj in objects) { Console.WriteLine($"Object Name: {obj.Name}"); diff --git a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs index fc06f447fc4..ec90cc4aafe 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs @@ -30,7 +30,7 @@ public class ListSoftDeletedVersionsOfObjectSample { var storage = StorageClient.Create(); var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true, MatchGlob = objectName }); - Console.WriteLine($"Soft Deleted Versions of the Object exist in the {bucketName}, identified by their respective Names and Versions are as follows:"); + Console.WriteLine($"The Name and Versions of the Soft Deleted Object in the Bucket (Bucket Name: {bucketName}) are as follows:"); foreach (var obj in objects) { Console.WriteLine($"Object Name: {obj.Name} and Version: {obj.Generation}"); diff --git a/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs b/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs index 41ffe85125a..bab812cbe02 100644 --- a/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs +++ b/storage/api/Storage.Samples/RestoreSoftDeletedObject.cs @@ -32,7 +32,7 @@ public Google.Apis.Storage.v1.Data.Object RestoreSoftDeletedObject( { var client = StorageClient.Create(); var restoredObject = client.RestoreObject(bucketName, objectName, generation); - Console.WriteLine($"The Name of the Restored Object after being previously soft deleted is : {restoredObject.Name}"); + Console.WriteLine($"The Name of the Restored Object which was previously Soft-deleted is : {restoredObject.Name}"); return restoredObject; } } From 3e9187b86bb5960081b56812bb681075c3f36e58 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Wed, 7 May 2025 04:53:43 -0700 Subject: [PATCH 6/9] license header minor changes --- storage/api/Storage.Samples/ListSoftDeletedObjects.cs | 2 +- storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs index d805c0ee082..6a3e9521185 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs @@ -1,4 +1,4 @@ -// Copyright 2025 Google Inc. +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs index ec90cc4aafe..e119ad12310 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs @@ -1,4 +1,4 @@ -// Copyright 2025 Google Inc. +// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 2e14cc8c2d4399412ef793e4fcee216506934c9e Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Wed, 7 May 2025 05:09:19 -0700 Subject: [PATCH 7/9] xml documentation added for new helper methods --- storage/api/Storage.Samples.Tests/StorageFixture.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/storage/api/Storage.Samples.Tests/StorageFixture.cs b/storage/api/Storage.Samples.Tests/StorageFixture.cs index 6161e7efe4f..f159b5843c8 100644 --- a/storage/api/Storage.Samples.Tests/StorageFixture.cs +++ b/storage/api/Storage.Samples.Tests/StorageFixture.cs @@ -239,8 +239,16 @@ internal Bucket CreateBucket(string name, bool multiVersion, bool softDelete = f internal string GenerateBucketName() => Guid.NewGuid().ToString(); + /// + /// Generate the name of the object. + /// + /// The objectName. internal string GenerateName() => Guid.NewGuid().ToString(); + /// + /// Generate the content of the object. + /// + /// The objectContent. internal string GenerateContent() => Guid.NewGuid().ToString(); /// From e147ea7c03ea48d1331ed54f4e3aba13a06ffbe7 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Mon, 12 May 2025 12:01:44 +0530 Subject: [PATCH 8/9] named argument changes in create bucket method --- .../api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs | 2 +- storage/api/Storage.Samples/ListSoftDeletedObjects.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs index 36fee8713fd..f2a8d9dc62d 100644 --- a/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs +++ b/storage/api/Storage.Samples.Tests/RestoreSoftDeletedObjectTest.cs @@ -31,7 +31,7 @@ public void RestoreSoftDeletedObject() UploadObjectFromMemorySample uploadObjectFromMemory = new UploadObjectFromMemorySample(); GetMetadataSample getMetadataSample = new GetMetadataSample(); var bucketName = _fixture.GenerateBucketName(); - _fixture.CreateBucket(bucketName, multiVersion: false, softDelete: true, registerForDeletion: true); + _fixture.CreateBucket(bucketName, multiVersion: false, softDelete: false, registerForDeletion: true); var objectName = _fixture.GenerateName(); var objectContent = _fixture.GenerateContent(); uploadObjectFromMemory.UploadObjectFromMemory(bucketName, objectName, objectContent); diff --git a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs index 6a3e9521185..580589384e2 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs @@ -28,7 +28,7 @@ public class ListSoftDeletedObjectsSample { var storage = StorageClient.Create(); var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true }); - Console.WriteLine($"Names of the Soft Deleted Objects in the Bucket (Bucket Name: {bucketName}) are as follows:"); + Console.WriteLine($"The Names of the Soft Deleted Objects in the Bucket (Bucket Name: {bucketName}) are as follows:"); foreach (var obj in objects) { Console.WriteLine($"Object Name: {obj.Name}"); From 16b0d8ef4616afa4a08452d596dbc566cdf98442 Mon Sep 17 00:00:00 2001 From: mahendra-google Date: Sun, 25 May 2025 21:30:06 -0700 Subject: [PATCH 9/9] Code review changes --- storage/api/Storage.Samples/ListSoftDeletedObjects.cs | 2 +- storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs index 580589384e2..505126145ba 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedObjects.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedObjects.cs @@ -27,7 +27,7 @@ public class ListSoftDeletedObjectsSample public IEnumerable ListSoftDeletedObjects(string bucketName = "your-unique-bucket-name") { var storage = StorageClient.Create(); - var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true }); + var objects = storage.ListObjects(bucketName, prefix: null, new ListObjectsOptions { SoftDeletedOnly = true }); Console.WriteLine($"The Names of the Soft Deleted Objects in the Bucket (Bucket Name: {bucketName}) are as follows:"); foreach (var obj in objects) { diff --git a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs index e119ad12310..31b6ca359d3 100644 --- a/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs +++ b/storage/api/Storage.Samples/ListSoftDeletedVersionsOfObject.cs @@ -29,7 +29,7 @@ public class ListSoftDeletedVersionsOfObjectSample string objectName = "your-object-name") { var storage = StorageClient.Create(); - var objects = storage.ListObjects(bucketName, null, new ListObjectsOptions { SoftDeletedOnly = true, MatchGlob = objectName }); + var objects = storage.ListObjects(bucketName, prefix: null, new ListObjectsOptions { SoftDeletedOnly = true, MatchGlob = objectName }); Console.WriteLine($"The Name and Versions of the Soft Deleted Object in the Bucket (Bucket Name: {bucketName}) are as follows:"); foreach (var obj in objects) {