Skip to content

Commit a76bcde

Browse files
committed
test: add tests for deletion after download
1 parent 0ec156b commit a76bcde

1 file changed

Lines changed: 200 additions & 0 deletions

File tree

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
using ByteSync.Common.Business.SharedFiles;
2+
using ByteSync.ServerCommon.Business.Auth;
3+
using ByteSync.ServerCommon.Business.Sessions;
4+
using ByteSync.ServerCommon.Business.Settings;
5+
using ByteSync.ServerCommon.Interfaces.Repositories;
6+
using ByteSync.ServerCommon.Interfaces.Services.Storage;
7+
using ByteSync.ServerCommon.Services;
8+
using FakeItEasy;
9+
using FluentAssertions;
10+
using Microsoft.Extensions.Logging;
11+
using Microsoft.Extensions.Options;
12+
13+
namespace ByteSync.ServerCommon.Tests.Services;
14+
15+
[TestFixture]
16+
public class SharedFilesServiceTests
17+
{
18+
private ISharedFilesRepository _sharedFilesRepository;
19+
private IAzureBlobStorageService _azureBlobStorageService;
20+
private ICloudflareR2Service _cloudflareR2Service;
21+
private ILogger<SharedFilesService> _logger;
22+
23+
[SetUp]
24+
public void SetUp()
25+
{
26+
_sharedFilesRepository = A.Fake<ISharedFilesRepository>();
27+
_azureBlobStorageService = A.Fake<IAzureBlobStorageService>();
28+
_cloudflareR2Service = A.Fake<ICloudflareR2Service>();
29+
_logger = A.Fake<ILogger<SharedFilesService>>();
30+
}
31+
32+
[Test]
33+
[TestCase(StorageProvider.AzureBlobStorage)]
34+
[TestCase(StorageProvider.CloudflareR2)]
35+
public async Task AssertFilePartIsDownloaded_WhenPartBecomesFullyDownloaded_DeletesObject_And_Unregisters_WhenRetentionDisabled(StorageProvider storageProvider)
36+
{
37+
// Arrange
38+
var appSettings = Options.Create(new AppSettings { RetainFilesAfterTransfer = false });
39+
var service = new SharedFilesService(_sharedFilesRepository, _azureBlobStorageService, _cloudflareR2Service, _logger, appSettings);
40+
41+
var partNumber = 1;
42+
var recipients = new List<string> { "A", "B" };
43+
var sharedFileDefinition = new SharedFileDefinition { Id = "file-1" };
44+
var preExisting = new SharedFileData(sharedFileDefinition, recipients, storageProvider)
45+
{
46+
TotalParts = 2,
47+
UploadedPartsNumbers = new HashSet<int> { 1, 2 },
48+
DownloadedBy = new Dictionary<int, HashSet<string>>
49+
{
50+
{ 1, new HashSet<string> { "A" } },
51+
{ 2, new HashSet<string> { "A", "B" } }
52+
}
53+
};
54+
55+
// Intercept AddOrUpdate to apply the update handler to our preExisting state
56+
A.CallTo(() => _sharedFilesRepository.AddOrUpdate(sharedFileDefinition, A<Func<SharedFileData?, SharedFileData>>._))
57+
.Invokes(call =>
58+
{
59+
var handler = call.GetArgument<Func<SharedFileData?, SharedFileData>>(1)!;
60+
handler(preExisting);
61+
})
62+
.Returns(Task.CompletedTask);
63+
64+
var client = new Client { ClientInstanceId = "B" };
65+
var parameters = new TransferParameters
66+
{
67+
SessionId = "session-1",
68+
SharedFileDefinition = sharedFileDefinition,
69+
PartNumber = partNumber,
70+
StorageProvider = storageProvider
71+
};
72+
73+
// Act
74+
await service.AssertFilePartIsDownloaded(client, parameters);
75+
76+
// Assert
77+
if (storageProvider == StorageProvider.AzureBlobStorage)
78+
{
79+
A.CallTo(() => _azureBlobStorageService.DeleteObject(sharedFileDefinition, partNumber))
80+
.MustHaveHappenedOnceExactly();
81+
A.CallTo(() => _cloudflareR2Service.DeleteObject(A<SharedFileDefinition>._, A<int>._))
82+
.MustNotHaveHappened();
83+
}
84+
else
85+
{
86+
A.CallTo(() => _cloudflareR2Service.DeleteObject(sharedFileDefinition, partNumber))
87+
.MustHaveHappenedOnceExactly();
88+
A.CallTo(() => _azureBlobStorageService.DeleteObject(A<SharedFileDefinition>._, A<int>._))
89+
.MustNotHaveHappened();
90+
}
91+
92+
A.CallTo(() => _sharedFilesRepository.Forget(sharedFileDefinition))
93+
.MustHaveHappenedOnceExactly();
94+
}
95+
96+
[Test]
97+
public async Task AssertFilePartIsDownloaded_WhenRetentionEnabled_DoesNotDeleteObject_ButUnregistersWhenFullyDownloaded()
98+
{
99+
// Arrange
100+
var appSettings = Options.Create(new AppSettings { RetainFilesAfterTransfer = true });
101+
var service = new SharedFilesService(_sharedFilesRepository, _azureBlobStorageService, _cloudflareR2Service, _logger, appSettings);
102+
103+
var partNumber = 1;
104+
var recipients = new List<string> { "A", "B" };
105+
var sharedFileDefinition = new SharedFileDefinition { Id = "file-2" };
106+
var preExisting = new SharedFileData(sharedFileDefinition, recipients, StorageProvider.AzureBlobStorage)
107+
{
108+
TotalParts = 1,
109+
UploadedPartsNumbers = new HashSet<int> { 1 },
110+
DownloadedBy = new Dictionary<int, HashSet<string>>
111+
{
112+
{ 1, new HashSet<string> { "A" } }
113+
}
114+
};
115+
116+
A.CallTo(() => _sharedFilesRepository.AddOrUpdate(sharedFileDefinition, A<Func<SharedFileData?, SharedFileData>>._))
117+
.Invokes(call =>
118+
{
119+
var handler = call.GetArgument<Func<SharedFileData?, SharedFileData>>(1)!;
120+
handler(preExisting);
121+
})
122+
.Returns(Task.CompletedTask);
123+
124+
var client = new Client { ClientInstanceId = "B" };
125+
var parameters = new TransferParameters
126+
{
127+
SessionId = "session-2",
128+
SharedFileDefinition = sharedFileDefinition,
129+
PartNumber = partNumber,
130+
StorageProvider = StorageProvider.AzureBlobStorage
131+
};
132+
133+
// Act
134+
await service.AssertFilePartIsDownloaded(client, parameters);
135+
136+
// Assert
137+
A.CallTo(() => _azureBlobStorageService.DeleteObject(A<SharedFileDefinition>._, A<int>._))
138+
.MustNotHaveHappened();
139+
A.CallTo(() => _cloudflareR2Service.DeleteObject(A<SharedFileDefinition>._, A<int>._))
140+
.MustNotHaveHappened();
141+
142+
A.CallTo(() => _sharedFilesRepository.Forget(sharedFileDefinition))
143+
.MustHaveHappenedOnceExactly();
144+
145+
// Also assert the in-memory state evolved to be fully downloaded for the part
146+
preExisting.IsPartFullyDownloaded(partNumber).Should().BeTrue();
147+
preExisting.IsFullyDownloaded.Should().BeTrue();
148+
}
149+
150+
[Test]
151+
public async Task AssertFilePartIsDownloaded_WhenPartNotFullyDownloaded_DoesNotDeleteOrUnregister()
152+
{
153+
// Arrange
154+
var appSettings = Options.Create(new AppSettings { RetainFilesAfterTransfer = false });
155+
var service = new SharedFilesService(_sharedFilesRepository, _azureBlobStorageService, _cloudflareR2Service, _logger, appSettings);
156+
157+
var partNumber = 1;
158+
var recipients = new List<string> { "A", "B" };
159+
var sharedFileDefinition = new SharedFileDefinition { Id = "file-3" };
160+
var preExisting = new SharedFileData(sharedFileDefinition, recipients, StorageProvider.AzureBlobStorage)
161+
{
162+
TotalParts = 2,
163+
UploadedPartsNumbers = new HashSet<int> { 1, 2 },
164+
DownloadedBy = new Dictionary<int, HashSet<string>>()
165+
};
166+
167+
A.CallTo(() => _sharedFilesRepository.AddOrUpdate(sharedFileDefinition, A<Func<SharedFileData?, SharedFileData>>._))
168+
.Invokes(call =>
169+
{
170+
var handler = call.GetArgument<Func<SharedFileData?, SharedFileData>>(1)!;
171+
handler(preExisting);
172+
})
173+
.Returns(Task.CompletedTask);
174+
175+
var client = new Client { ClientInstanceId = "A" };
176+
var parameters = new TransferParameters
177+
{
178+
SessionId = "session-3",
179+
SharedFileDefinition = sharedFileDefinition,
180+
PartNumber = partNumber,
181+
StorageProvider = StorageProvider.AzureBlobStorage
182+
};
183+
184+
// Act
185+
await service.AssertFilePartIsDownloaded(client, parameters);
186+
187+
// Assert
188+
A.CallTo(() => _azureBlobStorageService.DeleteObject(A<SharedFileDefinition>._, A<int>._))
189+
.MustNotHaveHappened();
190+
A.CallTo(() => _cloudflareR2Service.DeleteObject(A<SharedFileDefinition>._, A<int>._))
191+
.MustNotHaveHappened();
192+
A.CallTo(() => _sharedFilesRepository.Forget(A<SharedFileDefinition>._))
193+
.MustNotHaveHappened();
194+
195+
preExisting.IsPartFullyDownloaded(partNumber).Should().BeFalse();
196+
preExisting.IsFullyDownloaded.Should().BeFalse();
197+
}
198+
}
199+
200+

0 commit comments

Comments
 (0)