public async Task Run(CancellationToken cancellationToken) { global::System.Console.WriteLine("TEST: START WATCHDOG TESTS"); // Increase startup timeout, disable heartbeats await instanceClient.DreamDaemon.Update(new DreamDaemon { StartupTimeout = 45, HeartbeatSeconds = 0, }, cancellationToken); await ApiAssert.ThrowsException <ApiConflictException>(() => instanceClient.DreamDaemon.Update(new DreamDaemon { SoftShutdown = true, SoftRestart = true }, cancellationToken), ErrorCode.DreamDaemonDoubleSoft); await RunBasicTest(cancellationToken); // await RunLongRunningTestThenUpdate(cancellationToken); // await RunLongRunningTestThenUpdateWithByondVersionSwitch(cancellationToken); // Remove this deploy when the above tests are reenabled await DeployTestDme("LongRunning/long_running_test", DreamDaemonSecurity.Trusted, cancellationToken); await RunHeartbeatTest(cancellationToken); await StartAndLeaveRunning(cancellationToken); global::System.Console.WriteLine("TEST: END WATCHDOG TESTS"); }
async Task <Repository> Checkout(Repository updated, bool expectFailure, bool isRef, bool checkBusy, CancellationToken cancellationToken) { var newRef = isRef ? updated.Reference : updated.CheckoutSha; var checkingOut = await repositoryClient.Update(updated, cancellationToken); Assert.IsNotNull(checkingOut.ActiveJob); if (checkBusy) { await ApiAssert.ThrowsException <ConflictException>(() => repositoryClient.Read(cancellationToken), ErrorCode.RepoBusy); } await WaitForJob(checkingOut.ActiveJob, 30, expectFailure, cancellationToken); var result = await repositoryClient.Read(cancellationToken); if (!expectFailure) { if (isRef) { Assert.AreEqual(newRef, result.Reference); } else { Assert.IsTrue(result.RevisionInformation.CommitSha.StartsWith(newRef, StringComparison.OrdinalIgnoreCase)); } } Assert.AreEqual(result.RevisionInformation.CommitSha, result.RevisionInformation.OriginCommitSha); return(result); }
async Task TestDeleteDirectory(CancellationToken cancellationToken) { //try to delete non-existent var TestDir = new ConfigurationFile { Path = "/TestDeleteDir" }; await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false); //try to delete non-empty var file = await configurationClient.Write(new ConfigurationFile { Content = Encoding.UTF8.GetBytes("Hello world!"), Path = TestDir.Path + "/test.txt" }, cancellationToken).ConfigureAwait(false); Assert.IsTrue(FileExists(file)); await ApiAssert.ThrowsException <ConflictException>(() => configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken), ErrorCode.ConfigurationDirectoryNotEmpty).ConfigureAwait(false); file.Content = null; await configurationClient.Write(file, cancellationToken).ConfigureAwait(false); await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false); }
async Task TestDeleteDirectory(CancellationToken cancellationToken) { //try to delete non-existent var TestDir = new ConfigurationFileRequest { Path = "/TestDeleteDir" }; await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false); //try to delete non-empty const string TestString = "Hello world!"; using var uploadMs = new MemoryStream(Encoding.UTF8.GetBytes(TestString)); var file = await configurationClient.Write(new ConfigurationFileRequest { Path = TestDir.Path + "/test.txt" }, uploadMs, cancellationToken).ConfigureAwait(false); Assert.IsTrue(FileExists(file)); Assert.IsNull(file.LastReadHash); var updatedFileTuple = await configurationClient.Read(file, cancellationToken).ConfigureAwait(false); var updatedFile = updatedFileTuple.Item1; Assert.IsNotNull(updatedFile.LastReadHash); using (var downloadMemoryStream = new MemoryStream()) { using (var downloadStream = updatedFileTuple.Item2) { var requestStream = downloadStream as CachedResponseStream; Assert.IsNotNull(requestStream); var response = (HttpResponseMessage)requestStream.GetType().GetField("response", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(requestStream); Assert.AreEqual(response.Content.Headers.ContentType.MediaType, MediaTypeNames.Application.Octet); await downloadStream.CopyToAsync(downloadMemoryStream); } Assert.AreEqual(TestString, Encoding.UTF8.GetString(downloadMemoryStream.ToArray()).Trim()); } await ApiAssert.ThrowsException <ConflictException>(() => configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken), ErrorCode.ConfigurationDirectoryNotEmpty).ConfigureAwait(false); file.FileTicket = null; await configurationClient.Write(new ConfigurationFileRequest { Path = updatedFile.Path, LastReadHash = updatedFile.LastReadHash }, null, cancellationToken).ConfigureAwait(false); Assert.IsFalse(FileExists(file)); await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false); var tmp = (TestDir.Path?.StartsWith('/') ?? false) ? '.' + TestDir.Path : TestDir.Path; var path = Path.Combine(instance.Path, "Configuration", tmp); Assert.IsFalse(Directory.Exists(path)); }
async Task TestCustomInstalls(CancellationToken cancellationToken) { var byondInstaller = new PlatformIdentifier().IsWindows ? (IByondInstaller) new WindowsByondInstaller( Mock.Of <IProcessExecutor>(), new DefaultIOManager(), Mock.Of <ILogger <WindowsByondInstaller> >()) : new PosixByondInstaller( Mock.Of <IPostWriteHandler>(), new DefaultIOManager(), Mock.Of <ILogger <PosixByondInstaller> >()); // get the bytes for stable using var stableBytesMs = new MemoryStream( await byondInstaller.DownloadVersion(TestVersion, cancellationToken)); var test = await byondClient.SetActiveVersion( new ByondVersionRequest { Version = TestVersion, UploadCustomZip = true }, stableBytesMs, cancellationToken) .ConfigureAwait(false); Assert.IsNotNull(test.InstallJob); await WaitForJob(test.InstallJob, 60, false, null, cancellationToken).ConfigureAwait(false); var newSettings = await byondClient.ActiveVersion(cancellationToken); Assert.AreEqual(new Version(TestVersion.Major, TestVersion.Minor, 1), newSettings.Version); // test a few switches var installResponse = await byondClient.SetActiveVersion(new ByondVersionRequest { Version = TestVersion }, null, cancellationToken); Assert.IsNull(installResponse.InstallJob); await ApiAssert.ThrowsException <ApiConflictException>(() => byondClient.SetActiveVersion(new ByondVersionRequest { Version = new Version(TestVersion.Major, TestVersion.Minor, 2) }, null, cancellationToken), ErrorCode.ByondNonExistentCustomVersion); installResponse = await byondClient.SetActiveVersion(new ByondVersionRequest { Version = new Version(TestVersion.Major, TestVersion.Minor, 1) }, null, cancellationToken); Assert.IsNull(installResponse.InstallJob); }
async Task RunLimitTests(CancellationToken cancellationToken) { await ApiAssert.ThrowsException <ConflictException>(() => chatClient.Create(new ChatBotCreateRequest { Name = "asdf", ConnectionString = "asdf", Provider = ChatProvider.Irc }, cancellationToken), ErrorCode.ChatBotMax); var bots = await chatClient.List(null, cancellationToken); var ogDiscordBot = bots.First(bot => bot.Provider.Value == ChatProvider.Discord);; var discordBotReq = new ChatBotUpdateRequest { Id = ogDiscordBot.Id, Channels = ogDiscordBot.Channels.ToList(), ChannelLimit = 1 }; // We limited chat bots and channels to 1 and 2 respectively, try violating them discordBotReq.Channels.Add( new ChatChannel { IsAdminChannel = true, IsUpdatesChannel = false, IsWatchdogChannel = true, Tag = "butt", DiscordChannelId = discordBotReq.Channels.First().DiscordChannelId }); await ApiAssert.ThrowsException <ApiConflictException>(() => chatClient.Update(discordBotReq, cancellationToken), ErrorCode.ChatBotMaxChannels); var oldChannels = discordBotReq.Channels; discordBotReq.Channels = null; discordBotReq.ChannelLimit = 0; await ApiAssert.ThrowsException <ConflictException>(() => chatClient.Update(discordBotReq, cancellationToken), ErrorCode.ChatBotMaxChannels); discordBotReq.Channels = oldChannels; discordBotReq.ChannelLimit = null; await ApiAssert.ThrowsException <ConflictException>(() => chatClient.Update(discordBotReq, cancellationToken), ErrorCode.ChatBotMaxChannels); await ApiAssert.ThrowsException <ConflictException>(() => instanceClient.Update(new InstanceUpdateRequest { Id = metadata.Id, ChatBotLimit = 0 }, cancellationToken), ErrorCode.ChatBotMax); discordBotReq.ChannelLimit = 20; discordBotReq.Channels = null; await chatClient.Update(discordBotReq, cancellationToken); }
public async Task Run(CancellationToken cancellationToken) { global::System.Console.WriteLine("TEST: START WATCHDOG TESTS"); // Increase startup timeout, disable heartbeats var initialSettings = await instanceClient.DreamDaemon.Update(new DreamDaemon { StartupTimeout = 60, HeartbeatSeconds = 0, Port = IntegrationTest.DDPort }, cancellationToken); await ApiAssert.ThrowsException <ApiConflictException>(() => instanceClient.DreamDaemon.Update(new DreamDaemon { Port = 0 }, cancellationToken), ErrorCode.ModelValidationFailure); await ApiAssert.ThrowsException <ApiConflictException>(() => instanceClient.DreamDaemon.Update(new DreamDaemon { SoftShutdown = true, SoftRestart = true }, cancellationToken), ErrorCode.DreamDaemonDoubleSoft); await ApiAssert.ThrowsException <ConflictException>(() => instanceClient.DreamDaemon.CreateDump(cancellationToken), ErrorCode.WatchdogNotRunning); await ApiAssert.ThrowsException <ConflictException>(() => instanceClient.DreamDaemon.Restart(cancellationToken), ErrorCode.WatchdogNotRunning); await RunBasicTest(cancellationToken); await TestDMApiFreeDeploy(cancellationToken); await RunLongRunningTestThenUpdate(cancellationToken); await RunLongRunningTestThenUpdateWithNewDme(cancellationToken); await RunLongRunningTestThenUpdateWithByondVersionSwitch(cancellationToken); await RunHeartbeatTest(cancellationToken); await StartAndLeaveRunning(cancellationToken); await DumpTests(cancellationToken); System.Console.WriteLine("TEST: END WATCHDOG TESTS"); }
public async Task RunPreWatchdog(CancellationToken cancellationToken) { const string TestRefEnvVar = "TGS4_GITHUB_REF"; var envVar = Environment.GetEnvironmentVariable(TestRefEnvVar); string workingBranch = null; if (!String.IsNullOrWhiteSpace(envVar)) { workingBranch = envVar; Console.WriteLine($"TEST: Set working branch to '{workingBranch}' from env var '{TestRefEnvVar}'"); } if (workingBranch == null) { workingBranch = "master"; Console.WriteLine($"TEST: Set working branch to default '{workingBranch}'"); } var initalRepo = await repositoryClient.Read(cancellationToken); Assert.IsNotNull(initalRepo); Assert.IsNull(initalRepo.Origin); Assert.IsNull(initalRepo.Reference); Assert.IsNull(initalRepo.RevisionInformation); Assert.IsNull(initalRepo.ActiveJob); const string Origin = "https://github.com/tgstation/tgstation-server"; var cloneRequest = new RepositoryCreateRequest { Origin = new Uri(Origin), Reference = workingBranch, }; var clone = await repositoryClient.Clone(cloneRequest, cancellationToken).ConfigureAwait(false); await ApiAssert.ThrowsException <ConflictException>(() => repositoryClient.Read(cancellationToken), ErrorCode.RepoCloning); Assert.IsNotNull(clone); Assert.AreEqual(cloneRequest.Origin, clone.Origin); Assert.AreEqual(workingBranch, clone.Reference); Assert.IsNull(clone.RevisionInformation); Assert.IsNotNull(clone.ActiveJob); await WaitForJobProgressThenCancel(clone.ActiveJob, 20, cancellationToken).ConfigureAwait(false); var secondRead = await repositoryClient.Read(cancellationToken).ConfigureAwait(false); Assert.IsNotNull(secondRead); Assert.IsNull(secondRead.ActiveJob); clone = await repositoryClient.Clone(cloneRequest, cancellationToken).ConfigureAwait(false); await WaitForJob(clone.ActiveJob, 9000, false, null, cancellationToken).ConfigureAwait(false); var readAfterClone = await repositoryClient.Read(cancellationToken); Assert.AreEqual(cloneRequest.Origin, readAfterClone.Origin); Assert.AreEqual(workingBranch, readAfterClone.Reference); Assert.IsNotNull(readAfterClone.RevisionInformation); Assert.IsNotNull(readAfterClone.RevisionInformation.ActiveTestMerges); Assert.AreEqual(0, readAfterClone.RevisionInformation.ActiveTestMerges.Count); Assert.IsNotNull(readAfterClone.RevisionInformation.CommitSha); Assert.IsNotNull(readAfterClone.RevisionInformation.OriginCommitSha); Assert.IsNotNull(readAfterClone.RevisionInformation.CompileJobs); Assert.AreEqual(0, readAfterClone.RevisionInformation.CompileJobs.Count); Assert.IsNotNull(readAfterClone.RevisionInformation.OriginCommitSha); Assert.IsNull(readAfterClone.RevisionInformation.PrimaryTestMerge); Assert.AreEqual(readAfterClone.RevisionInformation.CommitSha, readAfterClone.RevisionInformation.OriginCommitSha); Assert.AreNotEqual(default, readAfterClone.RevisionInformation.Timestamp);
public async Task Run(Task repositoryTask, CancellationToken cancellationToken) { var deployJob = await dreamMakerClient.Compile(cancellationToken); deployJob = await WaitForJob(deployJob, 30, true, null, cancellationToken); Assert.IsTrue(deployJob.ErrorCode == ErrorCode.RepoCloning || deployJob.ErrorCode == ErrorCode.RepoMissing); var dmSettings = await dreamMakerClient.Read(cancellationToken); Assert.AreEqual(true, dmSettings.RequireDMApiValidation); Assert.AreEqual(null, dmSettings.ProjectName); await repositoryTask; // by alphabetization rules, it should discover api_free here if (!new PlatformIdentifier().IsWindows) { var updatedDM = await dreamMakerClient.Update(new DreamMakerRequest { ProjectName = "tests/DMAPI/ApiFree/api_free", ApiValidationPort = IntegrationTest.DMPort }, cancellationToken); Assert.AreEqual(IntegrationTest.DMPort, updatedDM.ApiValidationPort); Assert.AreEqual("tests/DMAPI/ApiFree/api_free", updatedDM.ProjectName); } else { var updatedDM = await dreamMakerClient.Update(new DreamMakerRequest { ApiValidationPort = IntegrationTest.DMPort }, cancellationToken); Assert.AreEqual(IntegrationTest.DMPort, updatedDM.ApiValidationPort); } var updatedDD = await dreamDaemonClient.Update(new DreamDaemonRequest { StartupTimeout = 5, Port = IntegrationTest.DDPort }, cancellationToken); Assert.AreEqual(5U, updatedDD.StartupTimeout); Assert.AreEqual(IntegrationTest.DDPort, updatedDD.Port); await ApiAssert.ThrowsException <ConflictException>(() => dreamDaemonClient.Update(new DreamDaemonRequest { Port = IntegrationTest.DMPort }, cancellationToken), ErrorCode.PortNotAvailable); await ApiAssert.ThrowsException <ConflictException>(() => dreamMakerClient.Update(new DreamMakerRequest { ApiValidationPort = IntegrationTest.DDPort }, cancellationToken), ErrorCode.PortNotAvailable); deployJob = await dreamMakerClient.Compile(cancellationToken); await WaitForJob(deployJob, 30, true, ErrorCode.DreamMakerNeverValidated, cancellationToken); const string FailProject = "tests/DMAPI/BuildFail/build_fail"; var updated = await dreamMakerClient.Update(new DreamMakerRequest { ProjectName = FailProject }, cancellationToken); Assert.AreEqual(FailProject, updated.ProjectName); deployJob = await dreamMakerClient.Compile(cancellationToken); await WaitForJob(deployJob, 30, true, ErrorCode.DreamMakerExitCode, cancellationToken); await dreamMakerClient.Update(new DreamMakerRequest { ProjectName = "tests/DMAPI/ThisDoesntExist/this_doesnt_exist" }, cancellationToken); deployJob = await dreamMakerClient.Compile(cancellationToken); await WaitForJob(deployJob, 30, true, ErrorCode.DreamMakerMissingDme, cancellationToken); }
public async Task RunPreWatchdog(CancellationToken cancellationToken) { const string TestRefEnvVar = "TGS4_GITHUB_REF"; var envVar = Environment.GetEnvironmentVariable(TestRefEnvVar); string workingBranch = null; if (!String.IsNullOrWhiteSpace(envVar)) { workingBranch = envVar; Console.WriteLine($"TEST: Set working branch to '{workingBranch}' from env var '{TestRefEnvVar}'"); } if (workingBranch == null) { workingBranch = "master"; Console.WriteLine($"TEST: Set working branch to default '{workingBranch}'"); } var initalRepo = await repositoryClient.Read(cancellationToken); Assert.IsNotNull(initalRepo); Assert.IsNull(initalRepo.Origin); Assert.IsNull(initalRepo.Reference); Assert.IsNull(initalRepo.RevisionInformation); Assert.IsNull(initalRepo.ActiveJob); const string Origin = "https://github.com/tgstation/tgstation-server"; initalRepo.Origin = new Uri(Origin); initalRepo.Reference = workingBranch; var clone = await repositoryClient.Clone(initalRepo, cancellationToken).ConfigureAwait(false); await ApiAssert.ThrowsException <ConflictException>(() => repositoryClient.Read(cancellationToken), ErrorCode.RepoCloning); Assert.IsNotNull(clone); Assert.AreEqual(initalRepo.Origin, clone.Origin); Assert.AreEqual(workingBranch, clone.Reference); Assert.IsNull(clone.RevisionInformation); Assert.IsNotNull(clone.ActiveJob); await WaitForJobProgressThenCancel(clone.ActiveJob, 20, cancellationToken).ConfigureAwait(false); var secondRead = await repositoryClient.Read(cancellationToken).ConfigureAwait(false); Assert.IsNotNull(secondRead); Assert.IsNull(secondRead.ActiveJob); clone = await repositoryClient.Clone(initalRepo, cancellationToken).ConfigureAwait(false); await WaitForJob(clone.ActiveJob, 900, false, null, cancellationToken).ConfigureAwait(false); var readAfterClone = await repositoryClient.Read(cancellationToken); Assert.AreEqual(initalRepo.Origin, readAfterClone.Origin); Assert.AreEqual(workingBranch, readAfterClone.Reference); Assert.IsNotNull(readAfterClone.RevisionInformation); Assert.IsNotNull(readAfterClone.RevisionInformation.ActiveTestMerges); Assert.AreEqual(0, readAfterClone.RevisionInformation.ActiveTestMerges.Count); Assert.IsNotNull(readAfterClone.RevisionInformation.CommitSha); Assert.IsNotNull(readAfterClone.RevisionInformation.OriginCommitSha); Assert.IsNotNull(readAfterClone.RevisionInformation.CompileJobs); Assert.AreEqual(0, readAfterClone.RevisionInformation.CompileJobs.Count); Assert.IsNotNull(readAfterClone.RevisionInformation.OriginCommitSha); Assert.IsNull(readAfterClone.RevisionInformation.PrimaryTestMerge); Assert.AreEqual(readAfterClone.RevisionInformation.CommitSha, readAfterClone.RevisionInformation.OriginCommitSha); readAfterClone.Origin = new Uri("https://github.com/tgstation/tgstation"); await ApiAssert.ThrowsException <ApiConflictException>(() => repositoryClient.Update(readAfterClone, cancellationToken), ErrorCode.RepoCantChangeOrigin); readAfterClone.Origin = new Uri(Origin); // checkout V3 and back readAfterClone.Reference = "V3"; var updated = await Checkout(readAfterClone, false, true, cancellationToken); // Specific SHA updated.CheckoutSha = "f43f5bd"; await ApiAssert.ThrowsException <ApiConflictException>(() => Checkout(updated, false, false, cancellationToken), ErrorCode.RepoMismatchShaAndReference); updated.Reference = null; updated = await Checkout(updated, false, false, cancellationToken); // Fake SHA updated.Reference = null; updated.CheckoutSha = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; updated = await Checkout(updated, true, false, cancellationToken); // Fake ref updated.Reference = "Tgs4IntegrationTestFakeBranchNeverNameABranchThis"; updated = await Checkout(updated, true, true, cancellationToken); // Back updated.Reference = workingBranch; updated = await Checkout(updated, false, true, cancellationToken); var testPRString = Environment.GetEnvironmentVariable("TGS4_TEST_PULL_REQUEST_NUMBER"); if (String.IsNullOrWhiteSpace(testPRString)) { testPRString = Environment.GetEnvironmentVariable("APPVEYOR_PULL_REQUEST_NUMBER"); } if (String.IsNullOrWhiteSpace(testPRString)) { testPRString = Environment.GetEnvironmentVariable("TRAVIS_PULL_REQUEST"); } if (String.IsNullOrWhiteSpace(testPRString)) { if (workingBranch == "dev") { testPRString = "957"; } else { testPRString = "958"; } } if (!int.TryParse(testPRString, out var prNumber)) { Assert.Inconclusive($"Invalid PR #: {testPRString}"); } await TestMergeTests(updated, prNumber, cancellationToken); }