public async Task <Api.Models.Instance> RunPreInstanceTest(CancellationToken cancellationToken)
        {
            var firstTest = await CreateTestInstance(cancellationToken).ConfigureAwait(false);

            //instances always start offline
            Assert.AreEqual(false, firstTest.Online);
            //check it exists
            Assert.IsTrue(Directory.Exists(firstTest.Path));

            var firstClient = instanceManagerClient.CreateClient(firstTest);
            await ApiAssert.ThrowsException <ConflictException>(() => firstClient.DreamDaemon.Start(cancellationToken), ErrorCode.InstanceOffline);

            //cant create instances in existent directories
            var testNonEmpty = Path.Combine(testRootPath, Guid.NewGuid().ToString());

            Directory.CreateDirectory(testNonEmpty);
            var testFile = Path.Combine(testNonEmpty, "asdf");
            await File.WriteAllBytesAsync(testFile, Array.Empty <byte>(), cancellationToken).ConfigureAwait(false);

            await ApiAssert.ThrowsException <ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
            {
                Path = testNonEmpty,
                Name = "NonEmptyTest"
            }, cancellationToken), ErrorCode.InstanceAtExistingPath).ConfigureAwait(false);

            //check it works for truly empty directories
            File.Delete(testFile);
            var secondTry = await instanceManagerClient.CreateOrAttach(new Api.Models.Instance
            {
                Path = Path.Combine(testRootPath, Guid.NewGuid().ToString()),
                Name = "NonEmptyTest"
            }, cancellationToken).ConfigureAwait(false);

            await Assert.ThrowsExceptionAsync <ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false);

            Assert.IsTrue(Directory.Exists(firstTest.Path));

            //can't create instances in installation directory
            await ApiAssert.ThrowsException <ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
            {
                Path = "./A/Local/Path",
                Name = "NoInstallDirTest"
            }, cancellationToken), ErrorCode.InstanceAtConflictingPath).ConfigureAwait(false);

            //can't create instances as children of other instances
            await ApiAssert.ThrowsException <ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
            {
                Path = Path.Combine(firstTest.Path, "subdir"),
                Name = "NoOtherInstanceDirTest"
            }, cancellationToken), ErrorCode.InstanceAtConflictingPath).ConfigureAwait(false);

            Assert.IsTrue(Directory.Exists(firstTest.Path));

            //can't move to existent directories
            await ApiAssert.ThrowsException <ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
            {
                Id   = firstTest.Id,
                Path = testNonEmpty
            }, cancellationToken), ErrorCode.InstanceAtExistingPath).ConfigureAwait(false);

            // test can't create instance outside of whitelist
            await ApiAssert.ThrowsException <ApiConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
            {
                Name         = "TestInstanceOutsideOfWhitelist",
                Path         = Path.Combine(testRootPath, "..", Guid.NewGuid().ToString()),
                Online       = true,
                ChatBotLimit = 1
            }, cancellationToken), ErrorCode.InstanceNotAtWhitelistedPath);

            //test basic move
            Directory.Delete(testNonEmpty);
            var initialPath = firstTest.Path;

            firstTest = await instanceManagerClient.Update(new Api.Models.Instance
            {
                Id   = firstTest.Id,
                Path = testNonEmpty
            }, cancellationToken).ConfigureAwait(false);

            Assert.IsNotNull(firstTest.MoveJob);

            do
            {
                firstTest = await instanceManagerClient.GetId(firstTest, cancellationToken).ConfigureAwait(false);

                await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
            } while (firstTest.MoveJob != null);
            Assert.IsTrue(Directory.Exists(firstTest.Path));

            //online it for real for component tests
            firstTest.Online            = true;
            firstTest.ConfigurationType = ConfigurationType.HostWrite;
            firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);

            Assert.AreEqual(true, firstTest.Online);
            Assert.AreEqual(ConfigurationType.HostWrite, firstTest.ConfigurationType);
            Assert.IsTrue(Directory.Exists(firstTest.Path));

            //can't move online instance
            await ApiAssert.ThrowsException <ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
            {
                Id   = firstTest.Id,
                Path = initialPath
            }, cancellationToken), ErrorCode.InstanceRelocateOnline).ConfigureAwait(false);

            Assert.IsTrue(Directory.Exists(firstTest.Path));

            return(firstTest);
        }
        public async Task Run(CancellationToken cancellationToken)
        {
            var firstTest = await CreateTestInstance(cancellationToken).ConfigureAwait(false);

            //instances always start offline
            Assert.AreEqual(false, firstTest.Online);
            //check it exists
            Assert.IsTrue(Directory.Exists(firstTest.Path));

            //cant create instances in existent directories
            var testNonEmpty = Path.Combine(testRootPath, Guid.NewGuid().ToString());

            Directory.CreateDirectory(testNonEmpty);
            await Assert.ThrowsExceptionAsync <ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
            {
                Path = testNonEmpty,
                Name = "NonEmptyTest"
            }, cancellationToken)).ConfigureAwait(false);

            await Assert.ThrowsExceptionAsync <ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false);

            //can't create instances in installation directory
            await Assert.ThrowsExceptionAsync <ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
            {
                Path = "./A/Local/Path",
                Name = "NoInstallDirTest"
            }, cancellationToken)).ConfigureAwait(false);

            //can't move to existent directories
            await Assert.ThrowsExceptionAsync <ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
            {
                Id   = firstTest.Id,
                Path = testNonEmpty
            }, cancellationToken)).ConfigureAwait(false);

            //test basic move
            Directory.Delete(testNonEmpty);
            var initialPath = firstTest.Path;

            firstTest = await instanceManagerClient.Update(new Api.Models.Instance
            {
                Id   = firstTest.Id,
                Path = testNonEmpty
            }, cancellationToken).ConfigureAwait(false);

            Assert.IsNotNull(firstTest.MoveJob);

            do
            {
                firstTest = await instanceManagerClient.GetId(firstTest, cancellationToken).ConfigureAwait(false);

                await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
            } while (firstTest.MoveJob != null);


            //online it for real for component tests
            firstTest.Online            = true;
            firstTest.ConfigurationType = ConfigurationType.HostWrite;
            firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);

            Assert.AreEqual(true, firstTest.Online);
            Assert.AreEqual(ConfigurationType.HostWrite, firstTest.ConfigurationType);

            //can't move online instance
            await Assert.ThrowsExceptionAsync <ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
            {
                Id   = firstTest.Id,
                Path = initialPath
            }, cancellationToken)).ConfigureAwait(false);

            var testSuite1 = new InstanceTest(instanceManagerClient.CreateClient(firstTest));
            await testSuite1.RunTests(cancellationToken).ConfigureAwait(false);

            //can regain permissions on instance without instance user
            var instanceClient  = instanceManagerClient.CreateClient(firstTest);
            var ourInstanceUser = await instanceClient.Users.Read(cancellationToken).ConfigureAwait(false);

            await instanceClient.Users.Delete(ourInstanceUser, cancellationToken).ConfigureAwait(false);

            await Assert.ThrowsExceptionAsync <InsufficientPermissionsException>(() => instanceClient.Users.Read(cancellationToken)).ConfigureAwait(false);

            await instanceManagerClient.Update(new Api.Models.Instance
            {
                Id = firstTest.Id
            }, cancellationToken).ConfigureAwait(false);

            ourInstanceUser = await instanceClient.Users.Read(cancellationToken).ConfigureAwait(false);

            //can't detach online instance
            await Assert.ThrowsExceptionAsync <ConflictException>(() => instanceManagerClient.Detach(firstTest, cancellationToken)).ConfigureAwait(false);

            firstTest.Online = false;
            firstTest        = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);

            await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);

            var instanceAttachFileName = (string)typeof(InstanceController).GetField("InstanceAttachFileName", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
            var attachPath             = Path.Combine(firstTest.Path, instanceAttachFileName);

            Assert.IsTrue(File.Exists(attachPath));

            //can recreate detached instance
            firstTest = await instanceManagerClient.CreateOrAttach(firstTest, cancellationToken).ConfigureAwait(false);

            //but only if the attach file exists
            await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);

            File.Delete(attachPath);
            await Assert.ThrowsExceptionAsync <ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false);
        }