/// <summary> /// Returns all methods that contain valid IL code based on the following naming convention: /// [FriendlyName]_Invalid_[ExpectedVerifierError1].[ExpectedVerifierError2]....[ExpectedVerifierErrorN] /// The method name must contain 2 '_' characters. /// 1. part: a friendly name /// 2. part: must be the word 'Invalid' (Case sensitive) /// 3. part: the expected VerifierErrors as string separated by '.'. /// E.g.: SimpleAdd_Invalid_ExpectedNumericType /// </summary> public static TheoryData <TestCase> GetMethodsWithInvalidIL() { var methodSelector = new Func <string[], MethodDefinitionHandle, TestCase>((mparams, methodHandle) => { if (mparams.Length == 3 && mparams[1] == "Invalid") { var expectedErrors = mparams[2].Split('.'); var verificationErros = new List <VerifierError>(); foreach (var item in expectedErrors) { if (Enum.TryParse(item, out VerifierError expectedError)) { verificationErros.Add(expectedError); } } var newItem = new InvalidILTestCase { MetadataToken = MetadataTokens.GetToken(methodHandle) }; if (expectedErrors.Length > 0) { newItem.ExpectedVerifierErrors = verificationErros; } return(newItem); } return(null); }); return(GetTestMethodsFromDll(methodSelector)); }
void TestMethodsWithInvalidIL(InvalidILTestCase invalidIL) { IEnumerable <VerificationResult> results = null; try { results = Verify(invalidIL); } catch { //in some cases ILVerify throws exceptions when things look too wrong to continue //currently these are not caught. In tests we just catch these and do the asserts. //Once these exceptions are better handled and ILVerify instead of crashing aborts the verification //gracefully we can remove this empty catch block. } finally { Assert.NotNull(results); Assert.Equal(invalidIL.ExpectedVerifierErrors.Count, results.Count()); foreach (var item in invalidIL.ExpectedVerifierErrors) { var actual = results.Select(e => e.Code.ToString()); Assert.True(results.Where(r => r.Code == item).Count() > 0, $"Actual errors were: {string.Join(",", actual)}"); } } }