diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/IntegrationTests/GitStoreIntegrationResetTests.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/IntegrationTests/GitStoreIntegrationResetTests.cs new file mode 100644 index 00000000000..05a7c5b2100 --- /dev/null +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/IntegrationTests/GitStoreIntegrationResetTests.cs @@ -0,0 +1,400 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Azure.Sdk.Tools.TestProxy.Common; +using Azure.Sdk.Tools.TestProxy.Console; +using Azure.Sdk.Tools.TestProxy.Store; +using Microsoft.Extensions.Logging; +using Xunit; + +namespace Azure.Sdk.Tools.TestProxy.Tests.IntegrationTests +{ + // Reset Test Scenarios involving https://github.com/Azure/azure-sdk-assets-integration + + // Setup: + // The files live under https://github.com/Azure/azure-sdk-assets-integration/tree/main/pull/scenarios. + // Each file contains nothing but a single version digit, which is used for verification purposes. + // Most of the scenarios involve restoring from a SHA, updating, adding, and/or deleting files locally + // and then performing a Reset and verifying that the only the files in the original SHA are there and + // they've been restored to what they were in the original SHA. + public class GitStoreIntegrationResetTests + { + private GitStore _defaultStore; + private ConsoleWrapperTester _consoleWrapperTester; + + // Right now, this is necessary for testing purposes but the real server won't have + // this issue. + public GitStoreIntegrationResetTests() + { + var loggerFactory = new LoggerFactory(); + DebugLogger.ConfigureLogger(loggerFactory); + _consoleWrapperTester = new ConsoleWrapperTester(); + _defaultStore = new GitStore(_consoleWrapperTester); + } + + // Scenario 1 - Changes to existing files only are detected and overridden with Reset response Y + // 1. Restore from SHA fc54d000d0427c4a68bc8962d40f957f59e14577 + // 2. Expect: 3 files with versions they were checked in with + // 3. Update one or more files, incrementing their version + // 4. Expect: files updated should be at version 2 + // 5. Reset with Y + // 6. Expect: each file should be at it's initial version, the version that was in the original SHA + [Theory(Skip = "Skipping because the integration branch permissions need to be set for the test suite to run.")] + //[Theory] + [InlineData( + @"{ + ""AssetsRepo"": ""Azure/azure-sdk-assets-integration"", + ""AssetsRepoPrefixPath"": ""pull/scenarios"", + ""AssetsRepoId"": """", + ""AssetsRepoBranch"": ""main"", + ""SHA"": ""fc54d000d0427c4a68bc8962d40f957f59e14577"" + }")] + public async Task Scenario1(string inputJson) + { + var folderStructure = new string[] + { + GitStoretests.AssetsJson + }; + + var testFolder = TestHelpers.DescribeTestFolder(inputJson, folderStructure); + try + { + var jsonFileLocation = Path.Join(testFolder, GitStoretests.AssetsJson); + + var parsedConfiguration = await _defaultStore.ParseConfigurationFile(jsonFileLocation); + await _defaultStore.Restore(jsonFileLocation); + + // Calling Path.GetFullPath of the Path.Combine will ensure any directory separators are normalized for + // the OS the test is running on. The reason being is that AssetsRepoPrefixPath, if there's a separator, + // will be a forward one as expected by git but on Windows this won't result in a usable path. + string localFilePath = Path.GetFullPath(Path.Combine(parsedConfiguration.AssetsRepoLocation, parsedConfiguration.AssetsRepoPrefixPath)); + + Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 1)); + + // Increment file versions to cause a change on disk + TestHelpers.IncrementFileVersion(localFilePath, "file1.txt"); + TestHelpers.IncrementFileVersion(localFilePath, "file3.txt"); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + + // Reset the cloned assets, reponse for overwrite = Y + _consoleWrapperTester.SetReadLineResponse("Y"); + await _defaultStore.Reset(jsonFileLocation); + + // Verify all files have been set back to their original versions + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 1)); + } + finally + { + DirectoryHelper.DeleteGitDirectory(testFolder); + } + } + + // Scenario 2 - Changes to existing files only are detected and retained with Reset response N + // 1. Restore from SHA fc54d000d0427c4a68bc8962d40f957f59e14577 + // 2. Expect: 3 files with versions they were checked in with + // 3. Update one or more files, incrementing their version + // 4. Expect: files updated should be at version 2 + // 5. Reset with N + // 6. Expect: file versions should be what they were in step 4 + [Theory(Skip = "Skipping because the integration branch permissions need to be set for the test suite to run.")] + //[Theory] + [InlineData( + @"{ + ""AssetsRepo"": ""Azure/azure-sdk-assets-integration"", + ""AssetsRepoPrefixPath"": ""pull/scenarios"", + ""AssetsRepoId"": """", + ""AssetsRepoBranch"": ""main"", + ""SHA"": ""fc54d000d0427c4a68bc8962d40f957f59e14577"" + }")] + public async Task Scenario2(string inputJson) + { + var folderStructure = new string[] + { + GitStoretests.AssetsJson + }; + + var testFolder = TestHelpers.DescribeTestFolder(inputJson, folderStructure); + try + { + var jsonFileLocation = Path.Join(testFolder, GitStoretests.AssetsJson); + + var parsedConfiguration = await _defaultStore.ParseConfigurationFile(jsonFileLocation); + await _defaultStore.Restore(jsonFileLocation); + + // Calling Path.GetFullPath of the Path.Combine will ensure any directory separators are normalized for + // the OS the test is running on. The reason being is that AssetsRepoPrefixPath, if there's a separator, + // will be a forward one as expected by git but on Windows this won't result in a usable path. + string localFilePath = Path.GetFullPath(Path.Combine(parsedConfiguration.AssetsRepoLocation, parsedConfiguration.AssetsRepoPrefixPath)); + + Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 1)); + + // Increment file versions to cause a change on disk + TestHelpers.IncrementFileVersion(localFilePath, "file1.txt"); + TestHelpers.IncrementFileVersion(localFilePath, "file3.txt"); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + + // Reset the cloned assets, reponse for overwrite = N + _consoleWrapperTester.SetReadLineResponse("N"); + await _defaultStore.Reset(jsonFileLocation); + + // Verify all files have been set back to their original versions + Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + + } + finally + { + DirectoryHelper.DeleteGitDirectory(testFolder); + } + } + + // Scenario 3 - Restore from SHA, add and remove files, Reset response Y + // 1. Restore from SHA 9e81fbb7d08c2df4cbdbfaffe79cde5d72f560d1 + // 2. Expect: 4 files with versions they were checked in with + // 3. Update add/remove files + // 4. Expect: Untouched files are the same versions as step 2, added files are version 1, removed files are gone + // 5. Reset with Y + // 6. Expect: each file should be at it's initial version, the version that was in the original SHA + [Theory(Skip = "Skipping because the integration branch permissions need to be set for the test suite to run.")] + //[Theory] + [InlineData( + @"{ + ""AssetsRepo"": ""Azure/azure-sdk-assets-integration"", + ""AssetsRepoPrefixPath"": ""pull/scenarios"", + ""AssetsRepoId"": """", + ""AssetsRepoBranch"": ""main"", + ""SHA"": ""9e81fbb7d08c2df4cbdbfaffe79cde5d72f560d1"" + }")] + public async Task Scenario3(string inputJson) + { + var folderStructure = new string[] + { + GitStoretests.AssetsJson + }; + + var testFolder = TestHelpers.DescribeTestFolder(inputJson, folderStructure); + try + { + var jsonFileLocation = Path.Join(testFolder, GitStoretests.AssetsJson); + + var parsedConfiguration = await _defaultStore.ParseConfigurationFile(jsonFileLocation); + await _defaultStore.Restore(jsonFileLocation); + + // Calling Path.GetFullPath of the Path.Combine will ensure any directory separators are normalized for + // the OS the test is running on. The reason being is that AssetsRepoPrefixPath, if there's a separator, + // will be a forward one as expected by git but on Windows this won't result in a usable path. + string localFilePath = Path.GetFullPath(Path.Combine(parsedConfiguration.AssetsRepoLocation, parsedConfiguration.AssetsRepoPrefixPath)); + + // Verify files from SHA + Assert.Equal(4, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file4.txt", 1)); + + // Delete a couple of files + File.Delete(Path.Combine(localFilePath, "file2.txt")); + File.Delete(Path.Combine(localFilePath, "file4.txt")); + // Add a file + TestHelpers.CreateFileWithInitialVersion(localFilePath, "file5.txt"); + + // Verify the set of files after the additions/deletions + Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file5.txt", 1)); + + // Reset the cloned assets, reponse for overwrite = Y + _consoleWrapperTester.SetReadLineResponse("Y"); + await _defaultStore.Reset(jsonFileLocation); + + // Verify the only files there are ones from the SHA + Assert.Equal(4, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file4.txt", 1)); + + } + finally + { + DirectoryHelper.DeleteGitDirectory(testFolder); + } + } + + // Scenario 4 - Restore from SHA, add and remove files, Reset response N + // 1. Restore from SHA 9e81fbb7d08c2df4cbdbfaffe79cde5d72f560d1 + // 2. Expect: 4 files with versions they were checked in with + // 3. Update add/remove files + // 4. Expect: Untouched files are the same versions as step 2, added files are version 1, removed files are gone + // 5. Reset with N + // 6. Expect: same files and same versions as step 4 + [Theory(Skip = "Skipping because the integration branch permissions need to be set for the test suite to run.")] + //[Theory] + [InlineData( + @"{ + ""AssetsRepo"": ""Azure/azure-sdk-assets-integration"", + ""AssetsRepoPrefixPath"": ""pull/scenarios"", + ""AssetsRepoId"": """", + ""AssetsRepoBranch"": ""main"", + ""SHA"": ""9e81fbb7d08c2df4cbdbfaffe79cde5d72f560d1"" + }")] + public async Task Scenario4(string inputJson) + { + var folderStructure = new string[] + { + GitStoretests.AssetsJson + }; + + var testFolder = TestHelpers.DescribeTestFolder(inputJson, folderStructure); + try + { + var jsonFileLocation = Path.Join(testFolder, GitStoretests.AssetsJson); + + var parsedConfiguration = await _defaultStore.ParseConfigurationFile(jsonFileLocation); + await _defaultStore.Restore(jsonFileLocation); + + // Calling Path.GetFullPath of the Path.Combine will ensure any directory separators are normalized for + // the OS the test is running on. The reason being is that AssetsRepoPrefixPath, if there's a separator, + // will be a forward one as expected by git but on Windows this won't result in a usable path. + string localFilePath = Path.GetFullPath(Path.Combine(parsedConfiguration.AssetsRepoLocation, parsedConfiguration.AssetsRepoPrefixPath)); + + // Verify files from SHA + Assert.Equal(4, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file4.txt", 1)); + + // Delete a couple of files + File.Delete(Path.Combine(localFilePath, "file2.txt")); + File.Delete(Path.Combine(localFilePath, "file4.txt")); + // Add a file + TestHelpers.CreateFileWithInitialVersion(localFilePath, "file5.txt"); + + // Verify the set of files after the additions/deletions + Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file5.txt", 1)); + + // Reset the cloned assets, reponse for overwrite = N + _consoleWrapperTester.SetReadLineResponse("N"); + await _defaultStore.Reset(jsonFileLocation); + + // Verify the only files were not restored from the SHA + Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file5.txt", 1)); + + } + finally + { + DirectoryHelper.DeleteGitDirectory(testFolder); + } + } + + // Scenario 5 - Restore from SHA, add and remove files, Reset response N, then Reset response Y + // 1. Restore from SHA 9e81fbb7d08c2df4cbdbfaffe79cde5d72f560d1 + // 2. Expect: 3 files with versions they were checked in with + // 3. Update add/remove files + // 4. Expect: Untouched files are the same versions as step 2, added files are version 1, removed files are gone + // 5. Reset with N + // 6. Expect: same files and same versions as step 4 + // 7. Reset with Y + // 8. Expect: same files and same versions as step 2 + [Theory(Skip = "Skipping because the integration branch permissions need to be set for the test suite to run.")] + //[Theory] + [InlineData( + @"{ + ""AssetsRepo"": ""Azure/azure-sdk-assets-integration"", + ""AssetsRepoPrefixPath"": ""pull/scenarios"", + ""AssetsRepoId"": """", + ""AssetsRepoBranch"": ""main"", + ""SHA"": ""bb2223a3aa0472ff481f8e1850e7647dc39fbfdd"" + }")] + public async Task Scenario5(string inputJson) + { + var folderStructure = new string[] + { + GitStoretests.AssetsJson + }; + + var testFolder = TestHelpers.DescribeTestFolder(inputJson, folderStructure); + try + { + var jsonFileLocation = Path.Join(testFolder, GitStoretests.AssetsJson); + + var parsedConfiguration = await _defaultStore.ParseConfigurationFile(jsonFileLocation); + await _defaultStore.Restore(jsonFileLocation); + + // Calling Path.GetFullPath of the Path.Combine will ensure any directory separators are normalized for + // the OS the test is running on. The reason being is that AssetsRepoPrefixPath, if there's a separator, + // will be a forward one as expected by git but on Windows this won't result in a usable path. + string localFilePath = Path.GetFullPath(Path.Combine(parsedConfiguration.AssetsRepoLocation, parsedConfiguration.AssetsRepoPrefixPath)); + + // Verify files from SHA + Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file4.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file5.txt", 1)); + + + // Delete a file + File.Delete(Path.Combine(localFilePath, "file4.txt")); + // Add a couple of files + TestHelpers.CreateFileWithInitialVersion(localFilePath, "file1.txt"); + TestHelpers.CreateFileWithInitialVersion(localFilePath, "file3.txt"); + + // Verify the set of files after the additions/deletions + Assert.Equal(4, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file5.txt", 1)); + + // Reset the cloned assets, reponse for overwrite = N + _consoleWrapperTester.SetReadLineResponse("N"); + await _defaultStore.Reset(jsonFileLocation); + + // Verify the files were not restored from the SHA + Assert.Equal(4, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file1.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file3.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file5.txt", 1)); + + // Reset the cloned assets, reponse for overwrite = Y + _consoleWrapperTester.SetReadLineResponse("Y"); + await _defaultStore.Reset(jsonFileLocation); + + // Verify files are from the SHA + Assert.Equal(3, System.IO.Directory.EnumerateFiles(localFilePath).Count()); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file2.txt", 2)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file4.txt", 1)); + Assert.True(TestHelpers.VerifyFileVersion(localFilePath, "file5.txt", 1)); + + } + finally + { + DirectoryHelper.DeleteGitDirectory(testFolder); + } + } + } +} diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/IntegrationTests/GitStoreIntegrationRestoreTests.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/IntegrationTests/GitStoreIntegrationRestoreTests.cs index b4abe7caecd..db719ed4e24 100644 --- a/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/IntegrationTests/GitStoreIntegrationRestoreTests.cs +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/IntegrationTests/GitStoreIntegrationRestoreTests.cs @@ -11,12 +11,12 @@ namespace Azure.Sdk.Tools.TestProxy.Tests.IntegrationTests { - // Pull Test Scenarios involving https://github.com/Azure/azure-sdk-assets-integration + // Restore Test Scenarios involving https://github.com/Azure/azure-sdk-assets-integration // Setup: // The files live under https://github.com/Azure/azure-sdk-assets-integration/tree/main/pull/scenarios. // Each file contains nothing but a single version digit, which is used for verification purposes. - // There are 3 pull test scenarios and each uses a different SHA. The scenarios are detailed down + // There are restore test scenarios and each uses a different SHA. The scenarios are detailed down // below with their test functions. public class GitStoreIntegrationRestoreTests { @@ -37,7 +37,8 @@ public GitStoreIntegrationRestoreTests() // Added file2.txt // Added file3.txt // Expect: each file should be version 1 - [Theory(Skip = "Skipping because we the integration branch permissions set for the test suite to run.")] + [Theory(Skip = "Skipping because the integration branch permissions need to be set for the test suite to run.")] + //[Theory] [InlineData( @"{ ""AssetsRepo"": ""Azure/azure-sdk-assets-integration"", @@ -90,6 +91,7 @@ public async Task Scenario1(string inputJson) // file3 version 2 // file4 version 1 [Theory(Skip = "Skipping because we the integration branch permissions set for the test suite to run.")] + //[Theory] [InlineData( @"{ ""AssetsRepo"": ""Azure/azure-sdk-assets-integration"", @@ -144,6 +146,7 @@ public async Task Scenario2(string inputJson) // file4 version 1 // file5 version 1 [Theory(Skip = "Skipping because we the integration branch permissions set for the test suite to run.")] + //[Theory] [InlineData( @"{ ""AssetsRepo"": ""Azure/azure-sdk-assets-integration"", diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/TestHelpers.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/TestHelpers.cs index d91b12ea2b5..2350dcb6e03 100644 --- a/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/TestHelpers.cs +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/TestHelpers.cs @@ -231,9 +231,8 @@ public static bool VerifyFileVersion(string testFolder, string fileName, int exp /// Verify the version, inside the file, for a given file inside of a test folder. /// /// The temporary test folder created by TestHelpers.DescribeTestFolder - /// The fileName whose version needs verification - /// The expected version in the file - public static bool IncrementFileVersion(string testFolder, string fileName) + /// The file whose version needs to be incremented + public static void IncrementFileVersion(string testFolder, string fileName) { string fullFileName = Path.Combine(testFolder, fileName); string stringVersion = ""; @@ -254,8 +253,24 @@ public static bool IncrementFileVersion(string testFolder, string fileName) { File.WriteAllText(fullFileName, (++intVersion).ToString()); } + } - return false; + /// + /// Create a new file with an initial version of 1 + /// + /// The temporary test folder created by TestHelpers.DescribeTestFolder + /// The file to be created + public static void CreateFileWithInitialVersion(string testFolder, string fileName) + { + string fullFileName = Path.Combine(testFolder, fileName); + + if (File.Exists(fullFileName)) + { + string errorString = String.Format("FileName {0} already exists", fullFileName); + throw new ArgumentException(errorString); + } + + File.WriteAllText(fullFileName, "1"); } } } diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/ConsoleWrapper.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/ConsoleWrapper.cs new file mode 100644 index 00000000000..ec1a9283348 --- /dev/null +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/ConsoleWrapper.cs @@ -0,0 +1,24 @@ + +using System; + +namespace Azure.Sdk.Tools.TestProxy.Console +{ + /// + /// Implementation of IConsoleWrapper that's simply a passthrough to the Console functions. + /// + public class ConsoleWrapper : IConsoleWrapper + { + public void Write(string message) + { + System.Console.Write(message); + } + public void WriteLine(string message) + { + System.Console.WriteLine(message); + } + public string ReadLine() + { + return System.Console.ReadLine(); + } + } +} diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/ConsoleWrapperTester.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/ConsoleWrapperTester.cs new file mode 100644 index 00000000000..c032419ff5a --- /dev/null +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/ConsoleWrapperTester.cs @@ -0,0 +1,44 @@ +using System; + +namespace Azure.Sdk.Tools.TestProxy.Console +{ + /// + /// Implementation of IConsoleWrapper that will be used to test commands, like Reset, that require user input. + /// + public class ConsoleWrapperTester : IConsoleWrapper + { + private string _readLineResponse; + + public ConsoleWrapperTester() { } + + /// + /// Overloaded constructor takes in a string that'll be returned as the ReadLine response. + /// + /// string that'll be returned as the ReadLine response + public ConsoleWrapperTester(string readLineResponse) + { + _readLineResponse = readLineResponse; + } + + /// + /// Set the ReadLine response. + /// + /// string that'll be returned as the ReadLine response + public void SetReadLineResponse(string readLineResponse) + { + _readLineResponse = readLineResponse; + } + public void Write(string message) + { + System.Console.Write(message); + } + public void WriteLine(string message) + { + System.Console.WriteLine(message); + } + public string ReadLine() + { + return _readLineResponse; + } + } +} diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/IConsoleWrapper.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/IConsoleWrapper.cs new file mode 100644 index 00000000000..04bcd2cbced --- /dev/null +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Console/IConsoleWrapper.cs @@ -0,0 +1,13 @@ +namespace Azure.Sdk.Tools.TestProxy.Console +{ + /// + /// IConsoleWrapper is just an interface around Console functions. This is necessary for testing + /// functions, like Reset, which require user input that we need to be able to control. + /// + public interface IConsoleWrapper + { + void Write(string message); + void WriteLine(string message); + string ReadLine(); + } +} diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Startup.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Startup.cs index 5605690eebe..54bf983e336 100644 --- a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Startup.cs +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Startup.cs @@ -17,6 +17,7 @@ using System.Reflection; using Microsoft.AspNetCore.Server.Kestrel.Core; using Azure.Sdk.Tools.TestProxy.Store; +using Azure.Sdk.Tools.TestProxy.Console; namespace Azure.Sdk.Tools.TestProxy { @@ -59,7 +60,7 @@ public static void Main(bool insecure = false, string storageLocation = null, st var semanticVersion = assembly.GetCustomAttribute().InformationalVersion; var assemblyVersion = assembly.GetName().Version; - Console.WriteLine($"{assemblyVersion.Major}.{assemblyVersion.Minor}.{assemblyVersion.Build}-dev.{semanticVersion}"); + System.Console.WriteLine($"{assemblyVersion.Major}.{assemblyVersion.Minor}.{assemblyVersion.Build}-dev.{semanticVersion}"); Environment.Exit(0); } @@ -123,12 +124,12 @@ public static void Main(bool insecure = false, string storageLocation = null, st if (dump) { var config = app.Services?.GetService(); - Console.WriteLine("Dumping Resolved Configuration Values:"); + System.Console.WriteLine("Dumping Resolved Configuration Values:"); if (config != null) { foreach (var c in config.AsEnumerable()) { - Console.WriteLine(c.Key + " = " + c.Value); + System.Console.WriteLine(c.Key + " = " + c.Value); } } } @@ -238,21 +239,21 @@ private static Thread PrintStatus(Func status, bool newLine, Cancellatio if (newLine) { - Console.WriteLine(obj); + System.Console.WriteLine(obj); } else { - Console.Write(obj); + System.Console.Write(obj); needsExtraNewline = true; } } if (needsExtraNewline) { - Console.WriteLine(); + System.Console.WriteLine(); } - Console.WriteLine(); + System.Console.WriteLine(); }); thread.Start(); diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitProcessHandler.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitProcessHandler.cs index 9ca8fafbe96..38b099e23b4 100644 --- a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitProcessHandler.cs +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitProcessHandler.cs @@ -157,8 +157,8 @@ public virtual bool TryRun(string arguments, GitAssetsConfiguration config, out result = new CommandResult() { ExitCode = process.ExitCode, - StdErr = stdOut, - StdOut = stdErr, + StdErr = stdErr, + StdOut = stdOut, Arguments = arguments }; } diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitStore.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitStore.cs index cd8784a6f9a..984459be280 100644 --- a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitStore.cs +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/GitStore.cs @@ -10,6 +10,7 @@ using System.Linq; using Azure.Sdk.Tools.TestProxy.Common.Exceptions; using Azure.Sdk.Tools.TestProxy.Common; +using Azure.Sdk.Tools.TestProxy.Console; namespace Azure.Sdk.Tools.TestProxy.Store { @@ -26,11 +27,20 @@ public class DirectoryEvaluation public class GitStore : IAssetsStore { private HttpClient httpClient = new HttpClient(); + private IConsoleWrapper _consoleWrapper; public GitProcessHandler GitHandler = new GitProcessHandler(); public string DefaultBranch = "main"; public string FileName = "assets.json"; - public GitStore() { } + public GitStore() + { + _consoleWrapper = new ConsoleWrapper(); + } + + public GitStore(IConsoleWrapper consoleWrapper) + { + _consoleWrapper = consoleWrapper; + } public GitStore(GitProcessHandler processHandler) { GitHandler = processHandler; @@ -119,15 +129,16 @@ public async Task Restore(string pathToAssetsJson) { } /// - /// Resets a cloned assets repository to the default contained within the assets.json targeted commit. + /// Resets a cloned assets repository to the default contained within the assets.json targeted commit. This + /// function should only be called by the user as the server will only use Restore. /// /// /// - // This should only ever be called by the user? - public async Task Reset(string pathToAssetsJson) { + public async Task Reset(string pathToAssetsJson) + { var config = await ParseConfigurationFile(pathToAssetsJson); var initialized = config.IsAssetsRepoInitialized(); - var allowReset = true; + var allowReset = false; if (!initialized) { @@ -138,7 +149,26 @@ public async Task Reset(string pathToAssetsJson) { if (pendingChanges.Length > 0) { - // TODO: Azure/azure-sdk-tools/3698 + _consoleWrapper.WriteLine("There are pending git chances, are you sure you want to reset? [Y|N]"); + while (true) + { + string response = _consoleWrapper.ReadLine(); + response = response.ToLowerInvariant(); + if (response.Equals("y")) + { + allowReset = true; + break; + } + else if (response.Equals("n")) + { + allowReset = false; + break; + } + else + { + _consoleWrapper.WriteLine("Please answer [Y|N]"); + } + } } if (allowReset) @@ -146,7 +176,7 @@ public async Task Reset(string pathToAssetsJson) { try { GitHandler.Run("checkout *", config); - GitHandler.Run("git clean -xdf", config); + GitHandler.Run("clean -xdf", config); } catch(GitProcessException e) { @@ -186,7 +216,9 @@ public string[] DetectPendingChanges(GitAssetsConfiguration config) if (!string.IsNullOrWhiteSpace(diffResult.StdOut)) { - var individualResults = diffResult.StdOut.Split(Environment.NewLine).Select(x => x.Trim()).ToArray(); + // Normally, we'd use Environment.NewLine here but this doesn't work on Windows since its NewLine is \r\n and + // Git's NewLine is just \n + var individualResults = diffResult.StdOut.Split("\n").Select(x => x.Trim()).ToArray(); return individualResults; } diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/IAssetsStore.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/IAssetsStore.cs index 695e199cf8a..161facea94e 100644 --- a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/IAssetsStore.cs +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/IAssetsStore.cs @@ -1,5 +1,6 @@ using System.IO; using System.Threading.Tasks; +using Azure.Sdk.Tools.TestProxy.Console; namespace Azure.Sdk.Tools.TestProxy.Store { diff --git a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/NullStore.cs b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/NullStore.cs index 4245be7c7c8..12f7a4c1318 100644 --- a/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/NullStore.cs +++ b/tools/test-proxy/Azure.Sdk.Tools.TestProxy/Store/NullStore.cs @@ -2,6 +2,7 @@ using System.Net; using System.Threading.Tasks; using Azure.Sdk.Tools.TestProxy.Common.Exceptions; +using Azure.Sdk.Tools.TestProxy.Console; namespace Azure.Sdk.Tools.TestProxy.Store {