async Task <IServerClient> CreateAdminClient(Uri url, CancellationToken cancellationToken)
        {
            var giveUpAt = DateTimeOffset.Now.AddSeconds(60);

            do
            {
                try
                {
                    return(await clientFactory.CreateFromLogin(
                               url,
                               User.AdminName,
                               User.DefaultAdminPassword,
                               attemptLoginRefresh : false,
                               cancellationToken : cancellationToken)
                           .ConfigureAwait(false));
                }
                catch (HttpRequestException)
                {
                    //migrating, to be expected
                    if (DateTimeOffset.Now > giveUpAt)
                    {
                        throw;
                    }
                    await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
                }
                catch (ServiceUnavailableException)
                {
                    // migrating, to be expected
                    if (DateTimeOffset.Now > giveUpAt)
                    {
                        throw;
                    }
                    await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
                }
            } while (true);
        }
        public async Task TestUpdateProtocol()
        {
            using var server    = new TestingServer();
            using var serverCts = new CancellationTokenSource();
            var cancellationToken = serverCts.Token;
            var serverTask        = server.Run(cancellationToken);

            try
            {
                IServerClient adminClient;

                var giveUpAt = DateTimeOffset.Now.AddSeconds(60);
                do
                {
                    try
                    {
                        adminClient = await clientFactory.CreateFromLogin(server.Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false);

                        break;
                    }
                    catch (HttpRequestException)
                    {
                        //migrating, to be expected
                        if (DateTimeOffset.Now > giveUpAt)
                        {
                            throw;
                        }
                        await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
                    }
                    catch (ServiceUnavailableException)
                    {
                        //migrating, to be expected
                        if (DateTimeOffset.Now > giveUpAt)
                        {
                            throw;
                        }
                        await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
                    }
                } while (true);

                var testUpdateVersion = new Version(4, 1, 4);
                using (adminClient)
                    //attempt to update to stable
                    await adminClient.Administration.Update(new Administration
                    {
                        NewVersion = testUpdateVersion
                    }, cancellationToken).ConfigureAwait(false);

                //wait up to 3 minutes for the dl and install
                await Task.WhenAny(serverTask, Task.Delay(TimeSpan.FromMinutes(3), cancellationToken)).ConfigureAwait(false);

                Assert.IsTrue(serverTask.IsCompleted, "Sever still running!");

                Assert.IsTrue(Directory.Exists(server.UpdatePath), "Update directory not present!");

                var updatedAssemblyPath = Path.Combine(server.UpdatePath, "Tgstation.Server.Host.dll");
                Assert.IsTrue(File.Exists(updatedAssemblyPath), "Updated assembly missing!");

                var updatedAssemblyVersion = FileVersionInfo.GetVersionInfo(updatedAssemblyPath);
                Assert.AreEqual(testUpdateVersion, Version.Parse(updatedAssemblyVersion.FileVersion).Semver());
            }
            finally
            {
                serverCts.Cancel();
                try
                {
                    await serverTask.ConfigureAwait(false);
                }
                catch (OperationCanceledException) { }
            }
            Assert.IsTrue(server.RestartRequested, "Server not requesting restart!");
        }