Public Access
Tell the keep-alive wire when the Files session opens and closes
HasLiveFileSession answers the phone's foreground-service question — is there a connection here that dying with the process would sever — and a bucket answers no, because HTTP holds nothing open. ActivityChanged now also fires at the end of MarkHostConnected and CloseSessionAsync, where both facts it reads are finally true together. Also makes the bucket pins test actually open a bucket: it never set Remote, so CONNECT dialled the auto-selected host, and its assertions passed only because that host had no pins either.
This commit is contained in:
@@ -8114,6 +8114,57 @@ public sealed class ShellFlowTests : IAsyncLifetime
|
||||
shell.Transfers.HasConnectedPins.ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// The phone's foreground-service question, proven at the view model rather than through Android: a
|
||||
/// connect that opens an SFTP session is exactly the transition <c>SessionKeepAlive</c> needs to hear
|
||||
/// about even when no transfer ever moves — see <see cref="TransfersViewModel.ActivityChanged"/>'s own
|
||||
/// remark for why the queue's own raise, in <c>OnTransferChanged</c>, cannot cover a connect that never
|
||||
/// touches <c>Transfers</c> at all.
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public async Task ConnectingATransfersHost_RaisesActivityChangedAndTurnsOnHasLiveFileSession()
|
||||
{
|
||||
var vault = await ReadyToConnectAsync();
|
||||
|
||||
shell.Transfers.Attach(vault, knownHosts);
|
||||
shell.Transfers.SelectedHost = shell.Transfers.Hosts[0];
|
||||
|
||||
var raised = 0;
|
||||
shell.Transfers.ActivityChanged += (_, _) => raised++;
|
||||
|
||||
await shell.Transfers.ConnectCommand.ExecuteAsync(null);
|
||||
|
||||
shell.Transfers.IsConnected.ShouldBeTrue(shell.Transfers.Status);
|
||||
shell.Transfers.HasLiveFileSession.ShouldBeTrue();
|
||||
raised.ShouldBeGreaterThan(0);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// The other half: a disconnect is as much a transition the service must hear about as a connect is,
|
||||
/// because it is the moment the connection <see cref="TransfersViewModel.HasLiveFileSession"/> promised
|
||||
/// was open stops being true — and the foreground service would otherwise keep the process alive over a
|
||||
/// session that has already closed.
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public async Task DisconnectingTheTransfersScreen_RaisesActivityChangedAndTurnsOffHasLiveFileSession()
|
||||
{
|
||||
var vault = await ReadyToConnectAsync();
|
||||
|
||||
shell.Transfers.Attach(vault, knownHosts);
|
||||
shell.Transfers.SelectedHost = shell.Transfers.Hosts[0];
|
||||
|
||||
await shell.Transfers.ConnectCommand.ExecuteAsync(null);
|
||||
shell.Transfers.HasLiveFileSession.ShouldBeTrue();
|
||||
|
||||
var raised = 0;
|
||||
shell.Transfers.ActivityChanged += (_, _) => raised++;
|
||||
|
||||
await shell.Transfers.DisconnectCommand.ExecuteAsync(null);
|
||||
|
||||
shell.Transfers.HasLiveFileSession.ShouldBeFalse();
|
||||
raised.ShouldBeGreaterThan(0);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// A bucket is an <c>IRemoteFileStore</c> with no <c>HostSecret</c> underneath it, so there is no
|
||||
/// <c>PinnedPaths</c> to read at all — see <see cref="TransfersViewModel.OpenBucketAsync"/>'s own remark.
|
||||
@@ -8137,15 +8188,56 @@ public sealed class ShellFlowTests : IAsyncLifetime
|
||||
vault.BucketEditorRegion = "eu-west-1";
|
||||
await vault.SaveObjectStoreCommand.ExecuteAsync(null);
|
||||
|
||||
// Remote is what ConnectAsync branches on, and Attach's RefreshHosts has already auto-selected the
|
||||
// host ReadyToConnectAsync left in the picker — without this line the command below dialled that
|
||||
// host, and every assertion here passed only because that host happens to have no pins either. The
|
||||
// ConnectedTo check is the proof the bucket path was actually taken.
|
||||
shell.Transfers.Remote = RemoteKind.Bucket;
|
||||
shell.Transfers.SelectedBucket = shell.Transfers.Buckets[0];
|
||||
|
||||
await shell.Transfers.ConnectCommand.ExecuteAsync(null);
|
||||
|
||||
shell.Transfers.ConnectedTo.ShouldBe("s3://backups");
|
||||
shell.Transfers.IsConnected.ShouldBeTrue(shell.Transfers.Status);
|
||||
shell.Transfers.ConnectedPinnedPaths.ShouldBeEmpty();
|
||||
shell.Transfers.HasConnectedPins.ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// A bucket is HTTP, per-request, with nothing open that a dying process would lose — see
|
||||
/// <see cref="TransfersViewModel.HasLiveFileSession"/>'s own remark. <c>IsConnected</c> alone would have
|
||||
/// answered this wrongly, which is exactly why the flag reads <c>ConnectedCipher</c> as well: nothing
|
||||
/// underneath a bucket ever sets it.
|
||||
/// </remarks>
|
||||
[Fact]
|
||||
public async Task ConnectingABucket_LeavesHasLiveFileSessionOff()
|
||||
{
|
||||
var vault = await ReadyToConnectAsync();
|
||||
|
||||
shell.Transfers.Attach(vault, knownHosts, buckets: new FakeObjectStoreFactory());
|
||||
|
||||
vault.NewObjectStoreCommand.Execute(null);
|
||||
vault.BucketEditorLabel = "Backups";
|
||||
vault.BucketEditorBucket = "backups";
|
||||
vault.BucketEditorAccessKeyId = "AKIAEXAMPLE";
|
||||
vault.BucketEditorSecretAccessKey = "a-secret-access-key";
|
||||
vault.BucketEditorRegion = "eu-west-1";
|
||||
await vault.SaveObjectStoreCommand.ExecuteAsync(null);
|
||||
|
||||
// ReadyToConnectAsync already left a host in the picker, and Attach's own RefreshHosts auto-selects
|
||||
// it — so without this the CONNECT command below would dial that host rather than open the bucket,
|
||||
// and a host with no pins would make ConnectedPinnedPathsEmpty-style assertions pass for the wrong
|
||||
// reason. Remote is what ConnectAsync actually branches on.
|
||||
shell.Transfers.Remote = RemoteKind.Bucket;
|
||||
shell.Transfers.SelectedBucket = shell.Transfers.Buckets[0];
|
||||
|
||||
await shell.Transfers.ConnectCommand.ExecuteAsync(null);
|
||||
|
||||
shell.Transfers.ConnectedTo.ShouldBe("s3://backups", "proof this opened the bucket rather than the host");
|
||||
shell.Transfers.IsConnected.ShouldBeTrue(shell.Transfers.Status);
|
||||
shell.Transfers.HasLiveFileSession.ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>A bucket that opens and lists as empty, so a bucket connect can be proven with no network.</summary>
|
||||
private sealed class FakeObjectStoreFactory : IObjectStoreFactory
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user