* Squashed commit of test rewrite changes fix missing priority speaker flag rewrite the TestChannelPermissionModify test add test for GuildPermission modify separate unit and integration tests, start writing channel and guild permission tests copy over the color tests copy over the emote tests copy the token utils tests make the mocked entities sealed classes copy the TypeReaderTests class properly dispose the CommandService in the TypeReaderTests start writing tests for EmbedBuilder and related classes test that properties throw ArgumentException when invalid add tests for the embed length property add withFooter tests finish adding tests to EmbedBuilder fix bug in value validation of EmbedFieldBuilder hey, these tests actually found a bug! add tests for the MentionUtils class add tests for the Format util class remove all of the old tests add analyzer tests (copied from old tests) add tests for the SnowflakeUtils class add integration tests these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then remove unnecessary launchSettings.json update outdated string don't create a new guild each time, as that can result in errors this can happen if a bot creates too many guilds without properly deleting them add some tests that show that guild can be modified await async assert add more measures that created channels are deleted when done remove "Test" prefix from test method names I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant Remove mention of old test project fix an issue from forgetting to await Assert.ThrowsAsync explicitly disable parallelization on integration tests add test for GuildPermission modify separate unit and integration tests, start writing channel and guild permission tests copy over the color tests copy over the emote tests make the mocked entities sealed classes properly dispose the CommandService in the TypeReaderTests fix bug in value validation of EmbedFieldBuilder hey, these tests actually found a bug! add tests for the MentionUtils class add tests for the Format util class remove all of the old tests add analyzer tests (copied from old tests) add tests for the SnowflakeUtils class add integration tests these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then remove unnecessary launchSettings.json update outdated string don't create a new guild each time, as that can result in errors this can happen if a bot creates too many guilds without properly deleting them add more measures that created channels are deleted when done remove "Test" prefix from test method names I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant Remove mention of old test project fix an issue from forgetting to await Assert.ThrowsAsync explicitly disable parallelization on integration tests update the azure CI build script separate execution of test projects so that if one fails the other will not pass one of the unit tests failed, but the analzyer tests passed fix test that would break in different timezones enable the integration tests (only on dev branch) * Squashed commit of test rewrite changes fix missing priority speaker flag rewrite the TestChannelPermissionModify test add test for GuildPermission modify separate unit and integration tests, start writing channel and guild permission tests copy over the color tests copy over the emote tests copy the token utils tests make the mocked entities sealed classes copy the TypeReaderTests class properly dispose the CommandService in the TypeReaderTests start writing tests for EmbedBuilder and related classes test that properties throw ArgumentException when invalid add tests for the embed length property add withFooter tests finish adding tests to EmbedBuilder fix bug in value validation of EmbedFieldBuilder hey, these tests actually found a bug! add tests for the MentionUtils class add tests for the Format util class remove all of the old tests add analyzer tests (copied from old tests) add tests for the SnowflakeUtils class add integration tests these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then remove unnecessary launchSettings.json update outdated string don't create a new guild each time, as that can result in errors this can happen if a bot creates too many guilds without properly deleting them add some tests that show that guild can be modified await async assert add more measures that created channels are deleted when done remove "Test" prefix from test method names I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant Remove mention of old test project fix an issue from forgetting to await Assert.ThrowsAsync explicitly disable parallelization on integration tests add test for GuildPermission modify separate unit and integration tests, start writing channel and guild permission tests copy over the color tests copy over the emote tests make the mocked entities sealed classes properly dispose the CommandService in the TypeReaderTests fix bug in value validation of EmbedFieldBuilder hey, these tests actually found a bug! add tests for the MentionUtils class add tests for the Format util class remove all of the old tests add analyzer tests (copied from old tests) add tests for the SnowflakeUtils class add integration tests these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then remove unnecessary launchSettings.json update outdated string don't create a new guild each time, as that can result in errors this can happen if a bot creates too many guilds without properly deleting them add more measures that created channels are deleted when done remove "Test" prefix from test method names I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant Remove mention of old test project fix an issue from forgetting to await Assert.ThrowsAsync explicitly disable parallelization on integration tests update the azure CI build script separate execution of test projects so that if one fails the other will not pass one of the unit tests failed, but the analzyer tests passed fix test that would break in different timezones enable the integration tests (only on dev branch) * Update mocked channels for changed SendFileAsync signature * comment out the integration tests from the build script no bot token is provided to this script, and use of integration tests in CI is questionable here * force rebuild because Azure linux build broke
129 lines
7.1 KiB
C#
129 lines
7.1 KiB
C#
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CodeActions;
|
|
using Microsoft.CodeAnalysis.CodeFixes;
|
|
using Microsoft.CodeAnalysis.Diagnostics;
|
|
using Microsoft.CodeAnalysis.Formatting;
|
|
//using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using Xunit;
|
|
|
|
namespace TestHelper
|
|
{
|
|
/// <summary>
|
|
/// Superclass of all Unit tests made for diagnostics with codefixes.
|
|
/// Contains methods used to verify correctness of codefixes
|
|
/// </summary>
|
|
public abstract partial class CodeFixVerifier : DiagnosticVerifier
|
|
{
|
|
/// <summary>
|
|
/// Returns the codefix being tested (C#) - to be implemented in non-abstract class
|
|
/// </summary>
|
|
/// <returns>The CodeFixProvider to be used for CSharp code</returns>
|
|
protected virtual CodeFixProvider GetCSharpCodeFixProvider()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the codefix being tested (VB) - to be implemented in non-abstract class
|
|
/// </summary>
|
|
/// <returns>The CodeFixProvider to be used for VisualBasic code</returns>
|
|
protected virtual CodeFixProvider GetBasicCodeFixProvider()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called to test a C# codefix when applied on the inputted string as a source
|
|
/// </summary>
|
|
/// <param name="oldSource">A class in the form of a string before the CodeFix was applied to it</param>
|
|
/// <param name="newSource">A class in the form of a string after the CodeFix was applied to it</param>
|
|
/// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
|
|
/// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
|
|
protected void VerifyCSharpFix(string oldSource, string newSource, int? codeFixIndex = null, bool allowNewCompilerDiagnostics = false)
|
|
{
|
|
VerifyFix(LanguageNames.CSharp, GetCSharpDiagnosticAnalyzer(), GetCSharpCodeFixProvider(), oldSource, newSource, codeFixIndex, allowNewCompilerDiagnostics);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called to test a VB codefix when applied on the inputted string as a source
|
|
/// </summary>
|
|
/// <param name="oldSource">A class in the form of a string before the CodeFix was applied to it</param>
|
|
/// <param name="newSource">A class in the form of a string after the CodeFix was applied to it</param>
|
|
/// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
|
|
/// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
|
|
protected void VerifyBasicFix(string oldSource, string newSource, int? codeFixIndex = null, bool allowNewCompilerDiagnostics = false)
|
|
{
|
|
VerifyFix(LanguageNames.VisualBasic, GetBasicDiagnosticAnalyzer(), GetBasicCodeFixProvider(), oldSource, newSource, codeFixIndex, allowNewCompilerDiagnostics);
|
|
}
|
|
|
|
/// <summary>
|
|
/// General verifier for codefixes.
|
|
/// Creates a Document from the source string, then gets diagnostics on it and applies the relevant codefixes.
|
|
/// Then gets the string after the codefix is applied and compares it with the expected result.
|
|
/// Note: If any codefix causes new diagnostics to show up, the test fails unless allowNewCompilerDiagnostics is set to true.
|
|
/// </summary>
|
|
/// <param name="language">The language the source code is in</param>
|
|
/// <param name="analyzer">The analyzer to be applied to the source code</param>
|
|
/// <param name="codeFixProvider">The codefix to be applied to the code wherever the relevant Diagnostic is found</param>
|
|
/// <param name="oldSource">A class in the form of a string before the CodeFix was applied to it</param>
|
|
/// <param name="newSource">A class in the form of a string after the CodeFix was applied to it</param>
|
|
/// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
|
|
/// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
|
|
private void VerifyFix(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string oldSource, string newSource, int? codeFixIndex, bool allowNewCompilerDiagnostics)
|
|
{
|
|
var document = CreateDocument(oldSource, language);
|
|
var analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document });
|
|
var compilerDiagnostics = GetCompilerDiagnostics(document);
|
|
var attempts = analyzerDiagnostics.Length;
|
|
|
|
for (int i = 0; i < attempts; ++i)
|
|
{
|
|
var actions = new List<CodeAction>();
|
|
var context = new CodeFixContext(document, analyzerDiagnostics[0], (a, d) => actions.Add(a), CancellationToken.None);
|
|
codeFixProvider.RegisterCodeFixesAsync(context).Wait();
|
|
|
|
if (!actions.Any())
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (codeFixIndex != null)
|
|
{
|
|
document = ApplyFix(document, actions.ElementAt((int)codeFixIndex));
|
|
break;
|
|
}
|
|
|
|
document = ApplyFix(document, actions.ElementAt(0));
|
|
analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document });
|
|
|
|
var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document));
|
|
|
|
//check if applying the code fix introduced any new compiler diagnostics
|
|
if (!allowNewCompilerDiagnostics && newCompilerDiagnostics.Any())
|
|
{
|
|
// Format and get the compiler diagnostics again so that the locations make sense in the output
|
|
document = document.WithSyntaxRoot(Formatter.Format(document.GetSyntaxRootAsync().Result, Formatter.Annotation, document.Project.Solution.Workspace));
|
|
newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document));
|
|
|
|
Assert.True(false,
|
|
string.Format("Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n",
|
|
string.Join("\r\n", newCompilerDiagnostics.Select(d => d.ToString())),
|
|
document.GetSyntaxRootAsync().Result.ToFullString()));
|
|
}
|
|
|
|
//check if there are analyzer diagnostics left after the code fix
|
|
if (!analyzerDiagnostics.Any())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//after applying all of the code fixes, compare the resulting string to the inputted one
|
|
var actual = GetStringFromDocument(document);
|
|
Assert.Equal(newSource, actual);
|
|
}
|
|
}
|
|
} |