Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/ILLink.Tasks.Tests/CommandRunner.cs146
-rw-r--r--test/ILLink.Tasks.Tests/HelloWorldTest.cs63
-rw-r--r--test/ILLink.Tasks.Tests/IntegrationTestBase.cs178
-rwxr-xr-xtest/ILLink.Tasks.Tests/MusicStoreReflection.xml97
-rw-r--r--test/ILLink.Tasks.Tests/MusicStoreTest.cs229
-rw-r--r--test/ILLink.Tasks.Tests/TestContext.cs113
-rw-r--r--test/ILLink.Tasks.Tests/WebApiTest.cs86
-rw-r--r--test/ILLink.Tasks.Tests/nuget/NuGet.config11
-rw-r--r--test/ILLink.Tasks.Tests/test.csproj39
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/AddedPseudoAttributeAttribute.cs10
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseExpectedLinkedBehaviorAttribute.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseInAssemblyAttribute.cs5
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectBodyModifiedAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExceptionHandlersModifiedAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectLocalsModifiedAttribute.cs8
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedExceptionHandlerSequenceAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedLocalsSequenceAttribute.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/IgnoreTestCaseAttribute.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAllTypesAndMembersInAssemblyAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAssemblyAttribute.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeAttribute.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeInAssemblyAttribute.cs66
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeOnFixedBufferTypeAttribute.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBackingFieldAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseOnTypeInAssemblyAttribute.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseTypeAttribute.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventAddMethodAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventRemoveMethodAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptFixedBufferAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInitializerData.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceAttribute.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceOnTypeInAssemblyAttribute.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberAttribute.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberInAssemblyAttribute.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferenceAttribute.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferencesInAssemblyAttribute.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceAttribute.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceInAssemblyAttribute.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSecurityAttribute.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSymbolsAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptTypeInAssemblyAttribute.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyAttribute.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAttributeInAssembly.cs66
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedForwarderAttribute.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedInterfaceOnTypeInAssemblyAttribute.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedMemberInAssemblyAttribute.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedPseudoAttributeAttribute.cs9
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedResourceInAssemblyAttribute.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedSymbolsAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedTypeInAssemblyAttribute.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/BaseMetadataAttribute.cs9
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/DefineAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/Il8nAttribute.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/IncludeBlacklistStepAttribute.cs10
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/KeepTypeForwarderOnlyAssembliesAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/NotATestCaseAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceAttribute.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceDependencyAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SandboxDependencyAttribute.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCSharpCompilerToUseAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAfterAttribute.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileArgumentAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAsLibraryAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAssemblyNameAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileResourceAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerActionAttribute.cs14
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerArgumentAttribute.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerCoreActionAttribute.cs14
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerKeepDebugMembersAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkPublicAndFamilyAttribute.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkSymbolsAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerResponseFileAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerUserActionAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/SkipUnresolvedAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Metadata/StripResourcesAttribute.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj121
-rw-r--r--test/Mono.Linker.Tests.Cases.Expectations/Support/PreserveDependencyAttribute.cs46
-rw-r--r--test/Mono.Linker.Tests.Cases/Advanced/DeadCodeElimination1.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/Advanced/FieldThatOnlyGetsSetIsRemoved.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnType.cs39
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs43
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerTypeProxyAttributeOnType.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnType.cs42
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs46
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnType.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.StructLayout/AutoClass.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.StructLayout/ExplicitClass.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.StructLayout/SequentialClass.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes.StructLayout/UnusedTypeWithSequentialLayoutIsRemoved.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AssemblyAttributeKeptInComplexCase.cs41
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnAssemblyIsKept.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnParameterInUsedMethodIsKept.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeIsKept.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInConstructorIsKept.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInDifferentNamespaceIsKept.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInFieldIsKept.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInPropertySetterIsKept.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithUsedSetter.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedFieldIsKept.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedMethodIsKept.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedPropertyIsKept.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs44
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs44
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs37
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs44
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs36
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly_Lib.cs6
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AssemblyAttributeKeptInComplexCase_Lib.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AttributeDefinedInReference.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReference.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReference2.cs4
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReferenceWithReference.cs8
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/FixedLengthArrayAttributesArePreserved.cs41
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs43
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs43
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs36
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs43
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/CoreLibrarySecurityAttributeTypesAreRemoved.cs43
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/SecurityAttributesOnUsedMethodAreRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/SecurityAttributesOnUsedTypeAreRemoved.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/AttributeDefinedAndUsedInOtherAssemblyIsKept.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/AttributeUsedByAttributeIsKept.cs102
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ComAttributesArePreserved.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ComAttributesAreRemovedWhenFeatureExcluded.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ContextStaticIsPreservedOnField.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/AssemblyWithUnusedAttributeOnReturnParameterDefinition.il54
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Forwarder.cs6
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Lib.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/FixedLengthArrayAttributesArePreserved.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ThreadStaticIsPreservedOnField.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeOnReturnTypeIsRemoved.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributePreservedViaLinkXmlIsKept.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributePreservedViaLinkXmlIsKept.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnAssemblyIsRemoved.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnMethodIsRemoved.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnModuleIsRemoved.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnParameterIsRemoved.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnPropertyIsRemoved.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnTypeIsRemoved.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeWithTypeForwarderIsRemoved.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnAssemblyIsKept.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnMethodIsKept.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnModuleIsKept.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnParameterIsKept.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnPropertyIsKept.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnTypeIsKept.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/SecurityAttributesOnUsedMethodAreKept.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Attributes/SecurityAttributesOnUsedTypeAreKept.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/BaseRemovedEventSource.cs81
-rw-r--r--test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomEventSource.cs47
-rw-r--r--test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/Excluded.cs63
-rw-r--r--test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/LocalsOfModifiedMethodAreRemoved.cs65
-rw-r--r--test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/NonEventWithLog.cs51
-rw-r--r--test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/StubbedMethodWithExceptionHandlers.cs74
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/ComplexNestedClassesHasUnusedRemoved.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/InitializerForArrayIsKept.cs40
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/InstantiatedTypeWithOverridesFromObject.cs44
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/InterfaceMethodImplementedOnBaseClassDoesNotGetStripped.cs37
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/MultiLevelNestedClassesAllRemovedWhenNonUsed.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/NestedDelegateInvokeMethodsPreserved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/NeverInstantiatedTypeWithOverridesFromObject.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UninvokedInterfaceMemberGetsRemoved.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedClassGetsRemoved.cs10
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedDelegateGetsRemoved.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedEnumGetsRemoved.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedEventGetsRemoved.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedFieldGetsRemoved.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedFieldsOfStructsAreKept.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedMethodGetsRemoved.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedNestedClassGetsRemoved.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedPropertyGetsRemoved.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UnusedPropertySetterRemoved.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedEnumIsKept.cs39
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs45
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs48
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedInterfaceIsKept.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedPropertyIsKept.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/Basic/UsedStructIsKept.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/CommandLine/Dependencies/ResponseFilesWork.rsp1
-rw-r--r--test/Mono.Linker.Tests.Cases/CommandLine/ResponseFilesWork.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/CoreLink/CanIncludeI18nAssemblies.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/CoreLink/CopyOfCoreLibrariesKeepsUnusedTypes.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/CoreLink/DelegateAndMulticastDelegateKeepInstantiatedReqs.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedTypeWithOverridesFromObject.cs48
-rw-r--r--test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedMethods.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedTypes.cs42
-rw-r--r--test/Mono.Linker.Tests.Cases/CoreLink/NeverInstantiatedTypeWithOverridesFromObject.cs42
-rw-r--r--test/Mono.Linker.Tests.Cases/CoreLink/NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs41
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/CorrectOverloadedMethodGetsStrippedInGenericClass.cs37
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/DerivedClassWithMethodOfSameNameAsBaseButDifferentNumberOfGenericParametersUnusedBaseWillGetStripped.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/GenericInstanceInterfaceMethodImplementedWithDifferentGenericArgumentNameDoesNotGetStripped.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameter.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase2.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/NewConstraintOnClass.cs37
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/OverrideWithAnotherVirtualMethodOfSameNameWithDifferentParameterType.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodInGenericClassIsNotStripped.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodInstanceInGenericClassIsNotStripped.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodWithNoParametersIsNotStripped.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfAbstractIsKept.cs42
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved2.cs46
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved3.cs45
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideThatAlsoFulfilsInterface.cs59
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.cs51
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.xml7
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.cs60
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.xml7
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UnusedAbstractMethodRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UnusedVirtualMethodRemoved.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UsedOverrideOfAbstractMethodIsKept.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UsedOverrideOfVirtualMethodIsKept.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.cs10
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplementingInterfaceMethodsNested.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplementingInterfaceMethodsNested2.cs39
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass2.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass3.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass4.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass5.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass6.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromConcreteTypeHasInterfaceMethodRemoved.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromInterfaceHasInterfaceMethodKept.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ExplicitInterfaceMethodWhichCreatesInstanceOfParentType.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter.cs136
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter.xml11
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter2.cs144
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter2.xml11
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter3.cs144
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter3.xml7
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeInOtherUsedOnlyByCopiedAssembly.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeOnlyUsedHasInterfacesRemoved.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceUsedOnlyAsConstraintIsKept.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il68
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndAssemblyPreserveAll.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndAssemblyPreserveAll.xml3
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveAll.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveAll.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs41
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethods.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethods.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ComInterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ExplicitInterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs40
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/GenericType.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/GenericWithConstraintDoesNotCauseOtherTypesToKeepInterface.cs41
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs40
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs51
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceFromCopiedAssemblyCanBeRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs53
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/LocalDowncastDoesNotCuaseOtherTypesToKeepInterface.cs47
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ObjectHardCastedToInterface.cs40
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/PreserveDependencyPreservesInterfaceMethod.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.xml7
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.xml7
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasInterfaceMethodPreservedViaXml.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasInterfaceMethodPreservedViaXml.xml7
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveFields.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveFields.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethods.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethods.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.cs37
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ArrayPassedAsParameter.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ArrayWithIndexAssignedToReturnValue.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/FieldDowncastedToInterface.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericType.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint2.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint3.cs58
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/InterfaceOnMultipleBases.cs42
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalDowncastedToInterface.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameter.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGeneric.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGenericWithConstraint.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGenericWithConstraint2.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ReturnValueDowncastedToInterface.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ObjectCastedToSecondInterfaceHasMemberRemovedButInterfaceKept.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/TypeGetsMarkedThatImplementsAlreadyMarkedInterfaceMethod.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsKept.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsRemovedWhenComFeatureExcluded.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceHasMethodPreservedViaXml.cs39
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceHasMethodPreservedViaXml.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceIsRemoved.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceHasMethodPreservedViaXml.cs36
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceHasMethodPreservedViaXml.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceTypeIsRemoved.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs42
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs53
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs57
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructImplementingInterfaceMethodsNested.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructImplementingInterfaceMethodsNested2.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromConcreteTypeHasInterfaceMethodRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromInterfaceHasInterfaceMethodKept.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceHasMethodPreservedViaXml.cs39
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceHasMethodPreservedViaXml.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceIsRemoved.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceHasMethodPreservedViaXml.cs36
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceHasMethodPreservedViaXml.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceTypeIsRemoved.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/HarderToDetectUnusedVirtualMethodGetsRemoved.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UnusedTypeWithOverrideOfVirtualMethodIsRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UnusedVirtualMethodRemoved.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UsedOverrideOfVirtualMethodIsKept.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UsedTypeWithOverrideOfVirtualMethodHasOverrideKept.cs29
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/VirtualMethodGetsPerservedIfBaseMethodGetsInvoked.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/VirtualMethodGetsStrippedIfImplementingMethodGetsInvokedDirectly.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/DefaultConstructorOfParameterIsRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/DefaultConstructorOfReturnTypeIsRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfParameterAreRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfReturnTypeAreRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfThisAreRemoved.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/DefaultConstructorOfReturnTypeIsNotRemoved.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedDefaultConstructorIsRemoved.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesAreNotRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesWhenHasThisAreNotRemoved.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/DefaultConstructorOfParameterIsRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/DefaultConstructorOfReturnTypeIsRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfParameterAreRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfReturnTypeAreRemoved.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfThisAreRemoved.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/DefaultConstructorOfReturnTypeIsNotRemoved.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedDefaultConstructorIsRemoved.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedFieldsOfTypesAreNotRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Libraries/CanLinkPublicApisOfLibrary.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Libraries/DefaultLibraryLinkBehavior.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Libraries/Dependencies/UserAssemblyActionWorks_Lib.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/Libraries/UserAssemblyActionWorks.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/AssemblyWithPreserveAll.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/AssemblyWithPreserveAll.xml4
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExcludedFeatureCom.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExcludedFeatureCom.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveTypesUsingRegex.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveTypesUsingRegex.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/CanPreserveAnExportedType_Forwarder.cs3
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/CanPreserveAnExportedType_Library.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Base.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.xml14
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library2.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/Dependencies/OnAssembly_Lib1.cs10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/Dependencies/OnAssembly_Lib2.cs10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnAssembly.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnAssembly.xml8
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnEvent.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnEvent.xml10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnField.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnField.xml10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnMethod.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnMethod.xml10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnProperty.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnProperty.xml10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnType.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnType.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/PreserveBackingFieldWhenPropertyIsKept.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/PreserveBackingFieldWhenPropertyIsKept.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.cs61
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.xml4
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedEventPreservedByLinkXmlIsKept.cs37
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedEventPreservedByLinkXmlIsKept.xml10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedFieldPreservedByLinkXmlIsKept.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedFieldPreservedByLinkXmlIsKept.xml12
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.cs85
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedMethodPreservedByLinkXmlIsKept.cs37
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedMethodPreservedByLinkXmlIsKept.xml10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedNestedTypePreservedByLinkXmlIsKept.cs14
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedNestedTypePreservedByLinkXmlIsKept.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedNonRequiredTypeIsRemoved.cs10
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedNonRequiredTypeIsRemoved.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedPropertyPreservedByLinkXmlIsKept.cs46
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedPropertyPreservedByLinkXmlIsKept.xml17
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeDeclarationPreservedByLinkXmlIsKept.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeDeclarationPreservedByLinkXmlIsKept.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.xml3
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlIsKept.cs14
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlIsKept.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlWithCommentIsKept.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlWithCommentIsKept.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.cs86
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveAllHasAllMembersPreserved.cs85
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveAllHasAllMembersPreserved.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveFieldsHasMethodsRemoved.cs66
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveFieldsHasMethodsRemoved.xml7
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveMethodsHasFieldsRemoved.cs74
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveMethodsHasFieldsRemoved.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingAndPreserveMembers.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingAndPreserveMembers.xml8
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingHasMembersRemoved.cs50
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingHasMembersRemoved.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredTypeIsKept.cs52
-rw-r--r--test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredTypeIsKept.xml7
-rw-r--r--test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj621
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInAssemblyLibrary.cs8
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs5
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase2.cs8
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary.cs9
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction_Lib.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyField.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethod.cs94
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInAssembly.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssembly.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyChained.cs42
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReference.cs45
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyWithEmbeddedXml.cs45
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssembly.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithEmbeddedXml.cs43
-rw-r--r--test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs32
-rw-r--r--test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithMcs.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Copied.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Lib.cs4
-rw-r--r--test/Mono.Linker.Tests.Cases/References/Dependencies/UserAssembliesAreLinkedByDefault_Library1.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases/References/Individual/CanSkipUnresolved.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/References/Individual/Dependencies/CanSkipUnresolved_Library.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/References/ReferencesAreRemovedWhenAllUsagesAreRemoved.cs30
-rw-r--r--test/Mono.Linker.Tests.Cases/References/UserAssembliesAreLinkedByDefault.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflection.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflectionWithDerivedType.cs40
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflectionWithReference.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyDependency.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyDependencyWithReference.cs4
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyImportedViaReflectionWithDerivedType_Base.cs5
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyImportedViaReflectionWithDerivedType_Reflect.cs8
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflectionWithDefaultBindingFlags.cs36
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/MightKeepExtraThings.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs40
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs161
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionAssemblyDoesntExist.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionInDifferentAssembly.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionLdstrIncomplete.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionLdstrValidButChanged.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionTypeDoesntExist.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionTypeNameIsSymbol.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Reflection/UsedViaReflectionIntegrationTest.cs64
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1_NotMatchingName.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.xml6
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsProcessed.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsProcessedAndKept.xml5
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/Dependencies/NonLinkerEmbeddedResourceHasNoImpact.xml2
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessed.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedAndKept.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Resources/NonLinkerEmbeddedResourceHasNoImpact.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Statics/DisableBeforeFieldInit/UnusedStaticFieldInitializer.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/Statics/ExplicitStaticCtor.cs48
-rw-r--r--test/Mono.Linker.Tests.Cases/Statics/MixedStaticFieldInitializerAndCtor.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/Statics/StaticFieldInitializer.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Statics/UnusedStaticConstructorGetsRemoved.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Statics/UnusedStaticFieldInitializer.cs22
-rw-r--r--test/Mono.Linker.Tests.Cases/Statics/UnusedStaticMethodGetsRemoved.cs23
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/AssemblyWithDefaultSymbols.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/AssemblyWithDefaultSymbolsAndSymbolLinkingEnabled.cs15
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithCompilerDefaultSymbols.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithEmbeddedPdbSymbols.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.cs11
-rwxr-xr-xtest/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.dllbin0 -> 3072 bytes
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdbbin0 -> 389 bytes
-rwxr-xr-xtest/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/compile.sh6
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.dllbin0 -> 3584 bytes
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.pdbbin0 -> 11776 bytes
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/compile.bat5
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPortablePdbSymbols.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdb.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs21
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteAction.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdb.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbAndSymbolLinkingEnabled.cs33
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbCopyAction.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbCopyActionAndSymbolLinkingEnabled.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbDeleteAction.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbDeleteActionAndSymbolLinkingEnabled.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdb.cs31
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbAndSymbolLinkingEnabled.cs35
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbCopyAction.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbCopyActionAndSymbolLinkingEnabled.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbDeleteAction.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbDeleteActionAndSymbolLinkingEnabled.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdb.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyAction.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteAction.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypes.cs65
-rw-r--r--test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs69
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCheckInitializersByIndex.cs34
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCompileILAssembly.cs19
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesUsingTypes.cs14
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResources.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResourcesWithCsc.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResourcesWithMcs.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithCsc.cs39
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithDebugPdbs.cs25
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithMsc.cs39
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanSandboxDependenciesUsingType.cs14
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/CanVerifyInterfacesOnTypesInAssembly.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesUsingTypes_LibSource1.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesUsingTypes_LibSource2.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.cs7
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.log1
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.txt1
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithCsc.txt1
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithCsc_Lib.cs9
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithMcs.txt1
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithMcs_Lib.cs9
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanSandboxDependenciesUsingType_Source1.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanSandboxDependenciesUsingType_Source2.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanVerifyInterfacesOnTypesInAssembly_Lib.cs20
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/ILAssemblySample.il42
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyAttributesInAssemblyWorks_Base.cs11
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyAttributesInAssemblyWorks_Lib.cs37
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyResourceInAssemblyAttributesBehavior.txt1
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/VerifyAttributesInAssemblyWorks.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/VerifyAttributesInAssemblyWorksWithStrings.cs38
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/VerifyDefineAttributeBehavior.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/VerifyExpectModifiedAttributesWork.cs85
-rw-r--r--test/Mono.Linker.Tests.Cases/TestFramework/VerifyResourceInAssemblyAttributesBehavior.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Tracing/Individual/CanDumpDependenciesToUncompressedXml.cs13
-rw-r--r--test/Mono.Linker.Tests.Cases/Tracing/Individual/CanEnableDependenciesDump.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases/Tracing/Individual/CanEnableReducedTracing.cs16
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ForwarderLibrary.cs3
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ImplementationLibrary.cs14
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/LibraryUsingForwarder.cs12
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ReferenceImplementationLibrary.cs17
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/TypeForwarderMissingReference.il37
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/MissingTargetReference.cs24
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssembliesKept.cs26
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssembliesRemoved.cs27
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.cs28
-rw-r--r--test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.xml4
-rw-r--r--test/Mono.Linker.Tests/Extensions/CecilExtensions.cs122
-rw-r--r--test/Mono.Linker.Tests/Extensions/NiceIO.cs922
-rw-r--r--test/Mono.Linker.Tests/Mono.Linker.Tests.csproj115
-rw-r--r--test/Mono.Linker.Tests/TestCases/IndividualTests.cs92
-rw-r--r--test/Mono.Linker.Tests/TestCases/TestCase.cs48
-rw-r--r--test/Mono.Linker.Tests/TestCases/TestDatabase.cs175
-rw-r--r--test/Mono.Linker.Tests/TestCases/TestSuites.cs154
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs746
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/CompilerOptions.cs14
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs17
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/FormattingUtils.cs59
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs72
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkXmlHelpers.cs30
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs19
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkerArgumentBuilder.cs180
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs8
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/ManagedCompilationResult.cs15
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/ObjectFactory.cs31
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs147
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs629
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs15
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/SourceAndDestinationPair.cs9
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseAssemblyResolver.cs38
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseCollector.cs163
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs357
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseLinkerOptions.cs21
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs271
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestCaseSandbox.cs151
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs135
-rw-r--r--test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs69
-rw-r--r--test/Mono.Linker.Tests/Tests/PreserveActionComparisonTests.cs30
-rw-r--r--test/Mono.Linker.Tests/Tests/TypeNameParserTests.cs121
-rw-r--r--test/Mono.Linker.Tests/packages.config6
673 files changed, 22231 insertions, 0 deletions
diff --git a/test/ILLink.Tasks.Tests/CommandRunner.cs b/test/ILLink.Tasks.Tests/CommandRunner.cs
new file mode 100644
index 000000000..efee6cbbd
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/CommandRunner.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Diagnostics;
+using System.Text;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace ILLink.Tests
+{
+ public class CommandRunner
+ {
+ protected readonly ITestOutputHelper outputHelper;
+
+ private string command;
+ private string args;
+ private string workingDir;
+ private string additionalPath;
+ private int timeout = Int32.MaxValue;
+ private string terminatingOutput;
+
+ public CommandRunner(string command, ITestOutputHelper outputHelper) {
+ this.command = command;
+ this.outputHelper = outputHelper;
+ }
+
+ public CommandRunner WithArguments(string args) {
+ this.args = args;
+ return this;
+ }
+
+ public CommandRunner WithWorkingDir(string workingDir) {
+ this.workingDir = workingDir;
+ return this;
+ }
+
+ public CommandRunner WithAdditionalPath(string additionalPath) {
+ this.additionalPath = additionalPath;
+ return this;
+ }
+
+ public CommandRunner WithTimeout(int timeout) {
+ this.timeout = timeout;
+ return this;
+ }
+
+ public CommandRunner WithTerminatingOutput(string terminatingOutput) {
+ this.terminatingOutput = terminatingOutput;
+ return this;
+ }
+
+ public int Run()
+ {
+ return Run(out string commandOutputUnused);
+ }
+
+ public int Run(out string commandOutput)
+ {
+ if (String.IsNullOrEmpty(command)) {
+ throw new Exception("No command was specified specified.");
+ }
+ if (outputHelper == null) {
+ throw new Exception("No output helper present.");
+ }
+ var psi = new ProcessStartInfo
+ {
+ FileName = command,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ };
+ outputHelper.WriteLine($"caller working directory: {Environment.CurrentDirectory}");
+ if (!String.IsNullOrEmpty(args)) {
+ psi.Arguments = args;
+ outputHelper.WriteLine($"{command} {args}");
+ } else {
+ outputHelper.WriteLine($"{command}");
+ }
+ if (!String.IsNullOrEmpty(workingDir)) {
+ outputHelper.WriteLine($"working directory: {workingDir}");
+ psi.WorkingDirectory = workingDir;
+ }
+ if (!String.IsNullOrEmpty(additionalPath)) {
+ string path = psi.Environment["PATH"];
+ psi.Environment["PATH"] = path + ";" + additionalPath;
+ }
+ var process = new Process();
+ process.StartInfo = psi;
+
+ // dotnet sets some environment variables that
+ // may cause problems in the child process.
+ psi.Environment.Remove("MSBuildExtensionsPath");
+ psi.Environment.Remove("MSBuildLoadMicrosoftTargetsReadOnly");
+ psi.Environment.Remove("MSBuildSDKsPath");
+ psi.Environment.Remove("VbcToolExe");
+ psi.Environment.Remove("CscToolExe");
+ psi.Environment.Remove("MSBUILD_EXE_PATH");
+
+ outputHelper.WriteLine("environment:");
+ foreach (var item in psi.Environment) {
+ outputHelper.WriteLine($"\t{item.Key}={item.Value}");
+ }
+
+ StringBuilder processOutput = new StringBuilder();
+ DataReceivedEventHandler handler = (sender, e) => {
+ processOutput.Append(e.Data);
+ processOutput.AppendLine();
+ };
+ StringBuilder processError = new StringBuilder();
+ DataReceivedEventHandler ehandler = (sender, e) => {
+ processError.Append(e.Data);
+ processError.AppendLine();
+ };
+ process.OutputDataReceived += handler;
+ process.ErrorDataReceived += ehandler;
+
+ // terminate process if output contains specified string
+ if (!String.IsNullOrEmpty(terminatingOutput)) {
+ DataReceivedEventHandler terminatingOutputHandler = (sender, e) => {
+ if (!String.IsNullOrEmpty(e.Data) && e.Data.Contains(terminatingOutput)) {
+ process.Kill();
+ }
+ };
+ process.OutputDataReceived += terminatingOutputHandler;
+ }
+
+ // start the process
+ process.Start();
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
+ if (!process.WaitForExit(timeout)) {
+ outputHelper.WriteLine($"killing process after {timeout} ms");
+ process.Kill();
+ }
+ // WaitForExit with timeout doesn't guarantee
+ // that the async output handlers have been
+ // called, so WaitForExit needs to be called
+ // afterwards.
+ process.WaitForExit();
+ string processOutputStr = processOutput.ToString();
+ string processErrorStr = processError.ToString();
+ outputHelper.WriteLine(processOutputStr);
+ outputHelper.WriteLine(processErrorStr);
+ commandOutput = processOutputStr;
+ return process.ExitCode;
+ }
+ }
+}
diff --git a/test/ILLink.Tasks.Tests/HelloWorldTest.cs b/test/ILLink.Tasks.Tests/HelloWorldTest.cs
new file mode 100644
index 000000000..23e4662c2
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/HelloWorldTest.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace ILLink.Tests
+{
+ public class HelloWorldTest : IntegrationTestBase
+ {
+ private string csproj;
+
+ public HelloWorldTest(ITestOutputHelper output) : base(output) {
+ csproj = SetupProject();
+ }
+
+ public string SetupProject()
+ {
+ string projectRoot = "helloworld";
+ string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj");
+
+ if (File.Exists(csproj)) {
+ output.WriteLine($"using existing project {csproj}");
+ return csproj;
+ }
+
+ if (Directory.Exists(projectRoot)) {
+ Directory.Delete(projectRoot, true);
+ }
+
+ Directory.CreateDirectory(projectRoot);
+ int ret = Dotnet("new console", projectRoot);
+ if (ret != 0) {
+ output.WriteLine("dotnet new failed");
+ Assert.True(false);
+ }
+
+ AddLinkerReference(csproj);
+
+ return csproj;
+ }
+
+ [Fact]
+ public void RunHelloWorldStandalone()
+ {
+ string executablePath = BuildAndLink(csproj, selfContained: true);
+ CheckOutput(executablePath, selfContained: true);
+ }
+
+ [Fact]
+ public void RunHelloWorldPortable()
+ {
+ string target = BuildAndLink(csproj, selfContained: false);
+ CheckOutput(target, selfContained: false);
+ }
+
+ void CheckOutput(string target, bool selfContained = false)
+ {
+ int ret = RunApp(target, out string commandOutput, selfContained: selfContained);
+ Assert.True(ret == 0);
+ Assert.True(commandOutput.Contains("Hello World!"));
+ }
+ }
+}
diff --git a/test/ILLink.Tasks.Tests/IntegrationTestBase.cs b/test/ILLink.Tasks.Tests/IntegrationTestBase.cs
new file mode 100644
index 000000000..99218ba3e
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/IntegrationTestBase.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace ILLink.Tests
+{
+ public class IntegrationTestBase
+ {
+ protected readonly ITestOutputHelper output;
+
+ protected readonly TestContext context;
+
+ public IntegrationTestBase(ITestOutputHelper output)
+ {
+ this.output = output;
+
+ // This sets up the context with some values specific to
+ // the setup of the linker repository. A different context
+ // should be used in order to run tests in a different
+ // environment.
+ this.context = TestContext.CreateDefaultContext();
+ }
+
+ protected int Dotnet(string args, string workingDir, string additionalPath = null)
+ {
+ return RunCommand(Path.GetFullPath(context.DotnetToolPath), args,
+ workingDir, additionalPath, out string commandOutput);
+ }
+
+ protected int RunCommand(string command, string args, int timeout = Int32.MaxValue)
+ {
+ return RunCommand(command, args, null, null, out string commandOutput, timeout);
+ }
+
+ protected int RunCommand(string command, string args, string workingDir)
+ {
+ return RunCommand(command, args, workingDir, null, out string commandOutput);
+ }
+
+ protected int RunCommand(string command, string args, string workingDir, string additionalPath,
+ out string commandOutput, int timeout = Int32.MaxValue, string terminatingOutput = null)
+ {
+ return (new CommandRunner(command, output))
+ .WithArguments(args)
+ .WithWorkingDir(workingDir)
+ .WithAdditionalPath(additionalPath)
+ .WithTimeout(timeout)
+ .WithTerminatingOutput(terminatingOutput)
+ .Run(out commandOutput);
+ }
+
+ /// <summary>
+ /// Run the linker on the specified project. This assumes
+ /// that the project already contains a reference to the
+ /// linker task package.
+ /// Optionally takes a list of root descriptor files.
+ /// Returns the path to the built app, either the renamed
+ /// host for self-contained publish, or the dll containing
+ /// the entry point.
+ /// </summary>
+ public string BuildAndLink(string csproj, List<string> rootFiles = null, Dictionary<string, string> extraPublishArgs = null, bool selfContained = false)
+ {
+ string demoRoot = Path.GetDirectoryName(csproj);
+
+ string publishArgs = $"publish -c {context.Configuration} /v:n /p:ShowLinkerSizeComparison=true";
+ if (selfContained) {
+ publishArgs += $" -r {context.RuntimeIdentifier}";
+ }
+ string rootFilesStr;
+ if (rootFiles != null && rootFiles.Any()) {
+ rootFilesStr = String.Join(";", rootFiles);
+ publishArgs += $" /p:LinkerRootDescriptors={rootFilesStr}";
+ }
+ if (extraPublishArgs != null) {
+ foreach (var item in extraPublishArgs) {
+ publishArgs += $" /p:{item.Key}={item.Value}";
+ }
+ }
+ int ret = Dotnet(publishArgs, demoRoot);
+
+ if (ret != 0) {
+ output.WriteLine("publish failed, returning " + ret);
+ Assert.True(false);
+ }
+
+ // detect the target framework for which the app was published
+ string tfmDir = Path.Combine(demoRoot, "bin", context.Configuration);
+ string tfm = Directory.GetDirectories(tfmDir).Select(p => Path.GetFileName(p)).Single();
+ string builtApp = Path.Combine(tfmDir, tfm);
+ if (selfContained) {
+ builtApp = Path.Combine(builtApp, context.RuntimeIdentifier);
+ }
+ builtApp = Path.Combine(builtApp, "publish",
+ Path.GetFileNameWithoutExtension(csproj));
+ if (selfContained) {
+ if (context.RuntimeIdentifier.Contains("win")) {
+ builtApp += ".exe";
+ }
+ } else {
+ builtApp += ".dll";
+ }
+ Assert.True(File.Exists(builtApp));
+ return builtApp;
+ }
+
+ public int RunApp(string target, out string processOutput, int timeout = Int32.MaxValue,
+ string terminatingOutput = null, bool selfContained = false)
+ {
+ Assert.True(File.Exists(target));
+ int ret;
+ if (selfContained) {
+ ret = RunCommand(
+ target, null,
+ Directory.GetParent(target).FullName,
+ null, out processOutput, timeout, terminatingOutput);
+ } else {
+ ret = RunCommand(
+ Path.GetFullPath(context.DotnetToolPath),
+ Path.GetFullPath(target),
+ Directory.GetParent(target).FullName,
+ null, out processOutput, timeout, terminatingOutput);
+ }
+ return ret;
+ }
+
+ protected void AddLinkerReference(string csproj)
+ {
+ var xdoc = XDocument.Load(csproj);
+ var ns = xdoc.Root.GetDefaultNamespace();
+ bool added = false;
+ foreach (var el in xdoc.Root.Elements(ns + "ItemGroup")) {
+ if (el.Elements(ns + "PackageReference").Any()) {
+ el.Add(new XElement(ns+"PackageReference",
+ new XAttribute("Include", context.TasksPackageName),
+ new XAttribute("Version", context.TasksPackageVersion)));
+ added = true;
+ break;
+ }
+ }
+ if (!added) {
+ xdoc.Root.Add(new XElement(ns + "ItemGroup",
+ new XElement(ns + "PackageReference",
+ new XAttribute("Include", context.TasksPackageName),
+ new XAttribute("Version", context.TasksPackageVersion))));
+ added= true;
+ }
+
+ using (var fs = new FileStream(csproj, FileMode.Create)) {
+ xdoc.Save(fs);
+ }
+ }
+
+ static void AddLinkerRoots(string csproj, List<string> rootFiles)
+ {
+ var xdoc = XDocument.Load(csproj);
+ var ns = xdoc.Root.GetDefaultNamespace();
+
+ var rootsItemGroup = new XElement(ns+"ItemGroup");
+ foreach (var rootFile in rootFiles) {
+ rootsItemGroup.Add(new XElement(ns+"LinkerRootFiles",
+ new XAttribute("Include", rootFile)));
+ }
+
+ var propertyGroup = xdoc.Root.Elements(ns + "PropertyGroup").First();
+ propertyGroup.AddAfterSelf(rootsItemGroup);
+
+ using (var fs = new FileStream(csproj, FileMode.Create)) {
+ xdoc.Save(fs);
+ }
+ }
+ }
+}
diff --git a/test/ILLink.Tasks.Tests/MusicStoreReflection.xml b/test/ILLink.Tasks.Tests/MusicStoreReflection.xml
new file mode 100755
index 000000000..e35f91155
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/MusicStoreReflection.xml
@@ -0,0 +1,97 @@
+<linker>
+ <!--- Called by Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions:.cctor -->
+ <assembly fullname="System.Linq.Queryable">
+ <type fullname="System.Linq.Queryable"/>
+ </assembly>
+
+ <assembly fullname="System.Linq.Expressions">
+ <!--- Called by System.Linq.Expressions.Expression:CreateLambda -->
+ <type fullname="System.Linq.Expressions.Expression`1"/>
+ <!--- Called by System.Runtime.CompilerServices.CallSite`1.CreateCustomNoMatchDelegate and System.Runtime.CompilerServices.CallSite`1.CreateCustomUpdateDelegate-->
+ <type fullname="System.Runtime.CompilerServices.CallSiteOps"/>
+ <type fullname="System.Dynamic.DynamicObject" >
+ <!--- Called by System.Dynamic.DynamicObject.MetaDynamic.BindBinaryOperation -->
+ <method name="TryBinaryOperation"/>
+ </type>
+ </assembly>
+
+ <assembly fullname="System.ComponentModel.TypeConverter">
+ <!-- Called by System.RuntimeTypeHandle.CreateInstance -->
+ <type fullname="System.ComponentModel.StringConverter">
+ <method name=".ctor"/>
+ </type>
+ <type fullname="System.ComponentModel.BooleanConverter">
+ <method name=".ctor"/>
+ </type>
+ <type fullname="System.ComponentModel.CollectionConverter">
+ <method name=".ctor"/>
+ </type>
+ </assembly>
+
+ <assembly fullname="Microsoft.CSharp">
+ <type fullname="Microsoft.CSharp.RuntimeBinder.Binder">
+ <!-- Called by AspNetCore._Views_Home_Index_cshtml.<ExecuteAsync>d__11.MoveNext() -->
+ <method name="Convert"/>
+ </type>
+ </assembly>
+
+ <assembly fullname="System.Dynamic.Runtime">
+ <type fullname="System.Runtime.CompilerServices.CallSite`1">
+ <!--- Called by [System.Dynamic.Runtime]System.Runtime.CompilerServices.CallSiteBinder.Stitch -->
+ <method name="get_Update"/>
+ </type>
+ </assembly>
+
+ <assembly fullname="System.Text.RegularExpressions">
+ <!--- System.Text.RegularExpressions.RegexCompiler -->
+ <type fullname="System.Text.RegularExpressions.RegexRunner">
+ <field name="runtextbeg"/>
+ <field name="runtextend"/>
+ <field name="runtextstart"/>
+ <field name="runtextpos"/>
+ <field name="runtext"/>
+ <field name="runtrackpos"/>
+ <field name="runtrack"/>
+ <field name="runstackpos"/>
+ <field name="runstack"/>
+ <field name="runtrackcount"/>
+ <method name="EnsureStorage"/>
+ <method name="Capture"/>
+ <method name="TransferCapture"/>
+ <method name="Uncapture"/>
+ <method name="IsMatched"/>
+ <method name="MatchLength"/>
+ <method name="MatchIndex"/>
+ <method name="IsBoundary"/>
+ <method name="CharInClass"/>
+ <method name="IsECMABoundary"/>
+ <method name="Crawlpos"/>
+ <method name="CheckTimeout"/>
+ </type>
+ </assembly>
+
+ <assembly fullname="System.Net.Sockets">
+ <type fullname="System.Net.Sockets.Socket/CachedTaskEventArgs">
+ <!--- Called by System.Net.Sockets.Socket.AcceptAsync -->
+ <method name=".ctor"/>
+ </type>
+ </assembly>
+
+ <assembly fullname="System.Private.CoreLib">
+ <!--- Reflection in Microsoft.Extensions.Internal.AwaitableInfo.IsTypeAwaitable-->
+ <type fullname="System.Runtime.CompilerServices.INotifyCompletion">
+ <method name="OnCompleted"/>
+ </type>
+ <!--- Reflection in Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.Internal.SqlServerDateAddTranslator..ctor-->
+ <type fullname="System.DateTime">
+ <method name="AddHours"/>
+ </type>
+ <type fullname="System.DateTimeOffset">
+ <method name="AddMonths"/>
+ <method name="AddDays"/>
+ <method name="AddHours"/>
+ <method name="AddMilliseconds"/>
+ </type>
+ </assembly>
+
+</linker>
diff --git a/test/ILLink.Tasks.Tests/MusicStoreTest.cs b/test/ILLink.Tasks.Tests/MusicStoreTest.cs
new file mode 100644
index 000000000..a28e996d2
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/MusicStoreTest.cs
@@ -0,0 +1,229 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using Xunit;
+using Xunit.Abstractions; // ITestOutputHelper
+
+namespace ILLink.Tests
+{
+ public class MusicStoreTest : IntegrationTestBase
+ {
+ private static List<string> rootFiles = new List<string> { "MusicStoreReflection.xml" };
+
+ private static string gitRepo = "http://github.com/aspnet/JitBench";
+ private static string repoName = "JitBench";
+
+ // Revision can also be a branch name. We generally
+ // want to ensure that we are able to link the latest
+ // MusicStore from the dev branch.
+ private static string gitRevision = "536f89ac6178246e58125401480b0a3b6406efe8";
+
+ // The version of Microsoft.NETCore.App that
+ // musicstore will run on (and deploy with, for
+ // self-contained deployments).
+ private static string runtimeVersion = "2.1.0-preview1-25915-01";
+
+ // The version of the SDK used to build and link
+ // musicstore.
+ private static string sdkVersion = "2.2.0-preview1-007525";
+
+ // The version of Microsoft.AspNetCore.All to publish with.
+ private static string aspNetVersion = "2.1.0-preview1-27654";
+
+ private static Dictionary<string, string> versionPublishArgs;
+ private static Dictionary<string, string> VersionPublishArgs
+ {
+ get {
+ if (versionPublishArgs != null) {
+ return versionPublishArgs;
+ }
+ versionPublishArgs = new Dictionary<string, string>();
+ versionPublishArgs.Add("JITBENCH_FRAMEWORK_VERSION", runtimeVersion);
+ versionPublishArgs.Add("JITBENCH_ASPNET_VERSION", aspNetVersion);
+ return versionPublishArgs;
+ }
+ }
+
+ private static string csproj;
+
+ public MusicStoreTest(ITestOutputHelper output) : base(output) {
+ csproj = SetupProject();
+
+ // MusicStore targets .NET Core 2.1, so it must be built
+ // using an SDK that can target 2.1. We obtain that SDK
+ // here.
+ context.DotnetToolPath = ObtainSDK(context.TestBin, repoName);
+ }
+
+ [Fact]
+ public void RunMusicStoreStandalone()
+ {
+ string executablePath = BuildAndLink(csproj, rootFiles, VersionPublishArgs, selfContained: true);
+ CheckOutput(executablePath, selfContained: true);
+ }
+
+ [Fact]
+ public void RunMusicStorePortable()
+ {
+ Dictionary<string, string> extraPublishArgs = new Dictionary<string, string>(VersionPublishArgs);
+ extraPublishArgs.Add("PublishWithAspNetCoreTargetManifest", "false");
+ string target = BuildAndLink(csproj, null, extraPublishArgs, selfContained: false);
+ CheckOutput(target, selfContained: false);
+ }
+
+ void CheckOutput(string target, bool selfContained = false)
+ {
+ int ret = RunApp(target, out string commandOutput, selfContained: selfContained);
+
+ Assert.True(commandOutput.Contains("Starting request to http://localhost:5000"));
+ Assert.True(commandOutput.Contains("Response: OK"));
+ Assert.True(commandOutput.Contains("Running 100 requests"));
+ Assert.True(ret == 0);
+ }
+
+ // returns path to .csproj project file
+ string SetupProject()
+ {
+ int ret;
+ string demoRoot = Path.Combine(repoName, Path.Combine("src", "MusicStore"));
+ string csproj = Path.Combine(demoRoot, "MusicStore.csproj");
+
+ if (File.Exists(csproj)) {
+ output.WriteLine($"using existing project {csproj}");
+ return csproj;
+ }
+
+ if (Directory.Exists(repoName)) {
+ Directory.Delete(repoName, true);
+ }
+
+ ret = RunCommand("git", $"clone {gitRepo} {repoName}");
+ if (ret != 0) {
+ output.WriteLine("git failed");
+ Assert.True(false);
+ }
+
+ if (!Directory.Exists(demoRoot)) {
+ output.WriteLine($"{demoRoot} does not exist");
+ Assert.True(false);
+ }
+
+ ret = RunCommand("git", $"checkout {gitRevision}", demoRoot);
+ if (ret != 0) {
+ output.WriteLine($"problem checking out revision {gitRevision}");
+ Assert.True(false);
+ }
+
+ // Copy root files into the project directory
+ CopyRootFiles(demoRoot);
+
+ // This is necessary because JitBench comes with a
+ // NuGet.Config that has a <clear /> line, preventing
+ // NuGet.Config sources defined in outer directories from
+ // applying.
+ string nugetConfig = Path.Combine(repoName, "NuGet.config");
+ AddLocalNugetFeedAfterClear(nugetConfig);
+
+ AddLinkerReference(csproj);
+
+ AddGlobalJson(repoName);
+
+ return csproj;
+ }
+
+ void AddGlobalJson(string repoDir)
+ {
+ string globalJson = Path.Combine(repoDir, "global.json");
+ string globalJsonContents = "{ \"sdk\": { \"version\": \"" + sdkVersion + "\" } }\n";
+ File.WriteAllText(globalJson, globalJsonContents);
+ }
+
+
+ string GetDotnetToolPath(string dotnetDir)
+ {
+ string dotnetToolName = Directory.GetFiles(dotnetDir)
+ .Select(p => Path.GetFileName(p))
+ .Where(p => p.Contains("dotnet"))
+ .Single();
+ string dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName);
+
+ if (!File.Exists(dotnetToolPath)) {
+ output.WriteLine("repo-local dotnet tool does not exist.");
+ Assert.True(false);
+ }
+
+ return dotnetToolPath;
+ }
+
+ string ObtainSDK(string rootDir, string repoDir)
+ {
+ int ret;
+ string dotnetDirName = ".dotnet";
+ string dotnetDir = Path.Combine(rootDir, dotnetDirName);
+ if (Directory.Exists(dotnetDir)) {
+ return GetDotnetToolPath(dotnetDir);
+ }
+
+ string dotnetInstall = Path.Combine(Path.GetFullPath(repoDir), "dotnet-install");
+ if (context.RuntimeIdentifier.Contains("win")) {
+ dotnetInstall += ".ps1";
+ } else {
+ dotnetInstall += ".sh";
+ }
+ if (!File.Exists(dotnetInstall)) {
+ output.WriteLine($"missing dotnet-install script at {dotnetInstall}");
+ Assert.True(false);
+ }
+
+ if (context.RuntimeIdentifier.Contains("win")) {
+ ret = RunCommand("powershell", $"{dotnetInstall} -SharedRuntime -InstallDir {dotnetDirName} -Channel master -Architecture x64 -Version {runtimeVersion}", rootDir);
+ if (ret != 0) {
+ output.WriteLine("failed to retrieve shared runtime");
+ Assert.True(false);
+ }
+ ret = RunCommand("powershell", $"{dotnetInstall} -InstallDir {dotnetDirName} -Channel master -Architecture x64 -Version {sdkVersion}", rootDir);
+ if (ret != 0) {
+ output.WriteLine("failed to retrieve sdk");
+ Assert.True(false);
+ }
+ } else {
+ ret = RunCommand(dotnetInstall, $"-sharedruntime -runtimeid {context.RuntimeIdentifier} -installdir {dotnetDirName} -channel master -architecture x64 -version {runtimeVersion}", rootDir);
+ if (ret != 0) {
+ output.WriteLine("failed to retrieve shared runtime");
+ Assert.True(false);
+ }
+ ret = RunCommand(dotnetInstall, $"-installdir {dotnetDirName} -channel master -architecture x64 -version {sdkVersion}", rootDir);
+ if (ret != 0) {
+ output.WriteLine("failed to retrieve sdk");
+ Assert.True(false);
+ }
+ }
+
+ return GetDotnetToolPath(dotnetDir);
+ }
+
+ static void CopyRootFiles(string demoRoot)
+ {
+ foreach (var rf in rootFiles) {
+ File.Copy(rf, Path.Combine(demoRoot, rf));
+ }
+ }
+
+ private void AddLocalNugetFeedAfterClear(string nugetConfig)
+ {
+ string localPackagePath = Path.GetFullPath(context.PackageSource);
+ var xdoc = XDocument.Load(nugetConfig);
+ var ns = xdoc.Root.GetDefaultNamespace();
+ var clear = xdoc.Root.Element(ns+"packageSources").Element(ns+"clear");
+ clear.Parent.Add(new XElement(ns+"add",
+ new XAttribute("key", "local linker feed"),
+ new XAttribute("value", localPackagePath)));
+
+ using (var fs = new FileStream(nugetConfig, FileMode.Create)) {
+ xdoc.Save(fs);
+ }
+ }
+ }
+}
diff --git a/test/ILLink.Tasks.Tests/TestContext.cs b/test/ILLink.Tasks.Tests/TestContext.cs
new file mode 100644
index 000000000..95e3d72ec
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/TestContext.cs
@@ -0,0 +1,113 @@
+using System;
+using System.IO;
+using System.Linq;
+using Microsoft.DotNet.PlatformAbstractions;
+
+namespace ILLink.Tests
+{
+ public class TestContext
+ {
+ /// <summary>
+ /// The name of the tasks package to add to the integration
+ /// projects.
+ /// </summary>
+ public string TasksPackageName { get; private set; }
+
+ /// <summary>
+ /// The version of the tasks package to add to the
+ /// integration projects.
+ /// </summary>
+ public string TasksPackageVersion { get; private set; }
+
+ /// <summary>
+ /// The path of the directory from which to get the linker
+ /// package.
+ /// </summary>
+ public string PackageSource { get; private set; }
+
+ /// <summary>
+ /// The path to the dotnet tool to use to run the
+ /// integration tests.
+ /// </summary>
+ public string DotnetToolPath { get; set; }
+
+ /// <summary>
+ /// The RID to use when restoring, building, and linking the
+ /// integration test projects.
+ /// </summary>
+ public string RuntimeIdentifier { get; private set; }
+
+ /// <summary>
+ /// The configuration to use to build the integration test
+ /// projects.
+ /// </summary>
+ public string Configuration { get; private set; }
+
+ /// <summary>
+ /// The root testbin directory. Used to install test
+ /// assets that don't depend on the configuration or
+ /// target framework.
+ /// </summary>
+ public string TestBin { get; private set; }
+
+ /// <summary>
+ /// This is the context from which tests will be run in the
+ /// linker repo. The local directory that contains the
+ /// linker integration packages (hard-coded here) is
+ /// searched for the tasks package. This assumes that only
+ /// one version of the package is present, and uses it to
+ /// unambiguously determine which pacakge to use in the tests.
+ /// </summary>
+ public static TestContext CreateDefaultContext()
+ {
+ var packageName = "ILLink.Tasks";
+ // test working directory is test project's <baseoutputpath>/<config>/<tfm>
+ var testBin = "../../";
+ var repoRoot = Path.Combine(testBin, "..", "..", "..");
+ var packageSource = Path.Combine(repoRoot, "src", "ILLink.Tasks", "bin", "nupkgs");
+ var tasksPackages = Directory.GetFiles(packageSource)
+ .Where(p => Path.GetExtension(p) == ".nupkg")
+ .Select(p => Path.GetFileNameWithoutExtension(p))
+ .Where(p => p.StartsWith(packageName));
+ var nPackages = tasksPackages.Count();
+ if (nPackages > 1) {
+ throw new Exception($"duplicate {packageName} packages in {packageSource}");
+ } else if (nPackages == 0) {
+ throw new Exception($"{packageName} package not found in {packageSource}");
+ }
+ var tasksPackage = tasksPackages.Single();
+ var version = tasksPackage.Remove(0, packageName.Length + 1);
+ var dotnetDir = Path.Combine(repoRoot, "corebuild", "Tools", "dotnetcli");
+ var dotnetToolNames = Directory.GetFiles(dotnetDir)
+ .Select(p => Path.GetFileName(p))
+ .Where(p => p.Contains("dotnet"));
+ var nTools = dotnetToolNames.Count();
+ if (nTools > 1) {
+ throw new Exception($"multiple dotnet tools in {dotnetDir}");
+ } else if (nTools == 0) {
+ throw new Exception($"no dotnet tool found in {dotnetDir}");
+ }
+ var dotnetToolName = dotnetToolNames.Single();
+ var dotnetToolPath = Path.Combine(dotnetDir, dotnetToolName);
+
+ var context = new TestContext();
+ context.PackageSource = packageSource;
+ context.TasksPackageName = packageName;
+ context.TasksPackageVersion = version;
+ context.DotnetToolPath = dotnetToolPath;
+ // This sets the RID to the RID of the currently-executing system.
+ context.RuntimeIdentifier = RuntimeEnvironment.GetRuntimeIdentifier();
+ // workaround: the osx.10.13-x64 RID doesn't exist yet.
+ // see https://github.com/dotnet/core-setup/issues/3301
+ if (context.RuntimeIdentifier == "osx.10.13-x64")
+ {
+ context.RuntimeIdentifier = "osx.10.12-x64";
+ }
+ // We want to build and link integration projects in the
+ // release configuration.
+ context.Configuration = "Release";
+ context.TestBin = testBin;
+ return context;
+ }
+ }
+}
diff --git a/test/ILLink.Tasks.Tests/WebApiTest.cs b/test/ILLink.Tasks.Tests/WebApiTest.cs
new file mode 100644
index 000000000..c7e8683e0
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/WebApiTest.cs
@@ -0,0 +1,86 @@
+using System;
+using System.IO;
+using System.Xml.Linq;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace ILLink.Tests
+{
+ public class WebApiTest : IntegrationTestBase
+ {
+ private string csproj;
+
+ public WebApiTest(ITestOutputHelper output) : base(output) {
+ csproj = SetupProject();
+ }
+
+ public string SetupProject()
+ {
+ string projectRoot = "webapi";
+ string csproj = Path.Combine(projectRoot, $"{projectRoot}.csproj");
+
+ if (File.Exists(csproj)) {
+ output.WriteLine($"using existing project {csproj}");
+ return csproj;
+ }
+
+ if (Directory.Exists(projectRoot)) {
+ Directory.Delete(projectRoot, true);
+ }
+
+ Directory.CreateDirectory(projectRoot);
+ int ret = Dotnet("new webapi", projectRoot);
+ if (ret != 0) {
+ output.WriteLine("dotnet new failed");
+ Assert.True(false);
+ }
+
+ PreventPublishFiltering(csproj);
+
+ AddLinkerReference(csproj);
+
+ return csproj;
+ }
+
+ // TODO: Remove this once we figure out what to do about apps
+ // that have the publish output filtered by a manifest
+ // file. It looks like aspnet has made this the default. See
+ // the bug at https://github.com/dotnet/sdk/issues/1160.
+ private void PreventPublishFiltering(string csproj) {
+ var xdoc = XDocument.Load(csproj);
+ var ns = xdoc.Root.GetDefaultNamespace();
+
+ var propertygroup = xdoc.Root.Element(ns + "PropertyGroup");
+
+ output.WriteLine("setting PublishWithAspNetCoreTargetManifest=false");
+ propertygroup.Add(new XElement(ns + "PublishWithAspNetCoreTargetManifest",
+ "false"));
+
+ using (var fs = new FileStream(csproj, FileMode.Create)) {
+ xdoc.Save(fs);
+ }
+ }
+
+ [Fact]
+ public void RunWebApiStandalone()
+ {
+ string executablePath = BuildAndLink(csproj, selfContained: true);
+ CheckOutput(executablePath, selfContained: true);
+ }
+
+ [Fact]
+ public void RunWebApiPortable()
+ {
+ string target = BuildAndLink(csproj, selfContained: false);
+ CheckOutput(target, selfContained: false);
+ }
+
+ void CheckOutput(string target, bool selfContained = false)
+ {
+ string terminatingOutput = "Now listening on: http://localhost:5000";
+ int ret = RunApp(target, out string commandOutput, 60000, terminatingOutput, selfContained: selfContained);
+ Assert.True(commandOutput.Contains("Application started. Press Ctrl+C to shut down."));
+ Assert.True(commandOutput.Contains(terminatingOutput));
+ }
+ }
+}
diff --git a/test/ILLink.Tasks.Tests/nuget/NuGet.config b/test/ILLink.Tasks.Tests/nuget/NuGet.config
new file mode 100644
index 000000000..95400251a
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/nuget/NuGet.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <packageSources>
+ <add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
+ <!-- When the tests are run from the repo's test bin directory,
+ this NuGet.config should be read to find the local package
+ directory. The path is relative to the test <baseoutputpath>/<config>/<tfm>
+ directory. -->
+ <add key="local linker packages" value="../../../../src/ILLink.Tasks/bin/nupkgs" />
+ </packageSources>
+</configuration>
diff --git a/test/ILLink.Tasks.Tests/test.csproj b/test/ILLink.Tasks.Tests/test.csproj
new file mode 100644
index 000000000..05e25199b
--- /dev/null
+++ b/test/ILLink.Tasks.Tests/test.csproj
@@ -0,0 +1,39 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>netcoreapp2.0</TargetFramework>
+
+ <IsPackable>false</IsPackable>
+ <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Content Include="MusicStoreReflection.xml">
+ <!-- It doesn't seem to get copied unless we specify this
+ explicitly. -->
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
+
+ <Target Name="CopyNuGetConfig"
+ AfterTargets="AfterBuild">
+ <Copy SourceFiles="nuget/NuGet.config" DestinationFolder="$(OutDir)" />
+ </Target>
+
+ <ItemGroup>
+ <Compile Include="CommandRunner.cs" />
+ <Compile Include="IntegrationTestBase.cs" />
+ <Compile Include="TestContext.cs" />
+ <Compile Include="MusicStoreTest.cs" />
+ <Compile Include="HelloWorldTest.cs" />
+ <Compile Include="WebApiTest.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" />
+ <PackageReference Include="xunit" Version="2.3.0" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.3.0" />
+ <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0" />
+ </ItemGroup>
+
+</Project>
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/AddedPseudoAttributeAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/AddedPseudoAttributeAttribute.cs
new file mode 100644
index 000000000..93f47e2dd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/AddedPseudoAttributeAttribute.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event, AllowMultiple = true, Inherited = false)]
+ public class AddedPseudoAttributeAttribute : BaseExpectedLinkedBehaviorAttribute {
+ public AddedPseudoAttributeAttribute (uint value)
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseExpectedLinkedBehaviorAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseExpectedLinkedBehaviorAttribute.cs
new file mode 100644
index 000000000..47f0f3415
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseExpectedLinkedBehaviorAttribute.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Diagnostics;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ /// <summary>
+ /// Base attribute for attributes that mark up the expected behavior of the linker on a member
+ /// </summary>
+ [Conditional("INCLUDE_EXPECTATIONS")]
+ public abstract class BaseExpectedLinkedBehaviorAttribute : Attribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseInAssemblyAttribute.cs
new file mode 100644
index 000000000..df1a80a13
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseInAssemblyAttribute.cs
@@ -0,0 +1,5 @@
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ public abstract class BaseInAssemblyAttribute : BaseExpectedLinkedBehaviorAttribute {
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectBodyModifiedAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectBodyModifiedAttribute.cs
new file mode 100644
index 000000000..078e1d873
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectBodyModifiedAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)]
+ public class ExpectBodyModifiedAttribute : BaseInAssemblyAttribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExceptionHandlersModifiedAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExceptionHandlersModifiedAttribute.cs
new file mode 100644
index 000000000..3ad662d85
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExceptionHandlersModifiedAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)]
+ public class ExpectExceptionHandlersModifiedAttribute : BaseInAssemblyAttribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectLocalsModifiedAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectLocalsModifiedAttribute.cs
new file mode 100644
index 000000000..f168e5fc2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectLocalsModifiedAttribute.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)]
+ public class ExpectLocalsModifiedAttribute : BaseInAssemblyAttribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedExceptionHandlerSequenceAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedExceptionHandlerSequenceAttribute.cs
new file mode 100644
index 000000000..e5071b967
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedExceptionHandlerSequenceAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)]
+ public class ExpectedExceptionHandlerSequenceAttribute : BaseInAssemblyAttribute {
+ public ExpectedExceptionHandlerSequenceAttribute (string[] types)
+ {
+ if (types == null)
+ throw new ArgumentNullException ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceAttribute.cs
new file mode 100644
index 000000000..57c87ef64
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)]
+ public class ExpectedInstructionSequenceAttribute : BaseInAssemblyAttribute {
+ public ExpectedInstructionSequenceAttribute (string[] opCodes)
+ {
+ if (opCodes == null)
+ throw new ArgumentNullException ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedLocalsSequenceAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedLocalsSequenceAttribute.cs
new file mode 100644
index 000000000..73d220588
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedLocalsSequenceAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)]
+ public class ExpectedLocalsSequenceAttribute : BaseInAssemblyAttribute {
+ public ExpectedLocalsSequenceAttribute (string [] types)
+ {
+ if (types == null)
+ throw new ArgumentNullException ();
+ }
+
+ public ExpectedLocalsSequenceAttribute (Type [] types)
+ {
+ if (types == null)
+ throw new ArgumentNullException ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/IgnoreTestCaseAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/IgnoreTestCaseAttribute.cs
new file mode 100644
index 000000000..cf6d75094
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/IgnoreTestCaseAttribute.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class)]
+ public class IgnoreTestCaseAttribute : Attribute {
+
+ public IgnoreTestCaseAttribute (string reason)
+ {
+ if (reason == null)
+ throw new ArgumentNullException (nameof (reason));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAllTypesAndMembersInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAllTypesAndMembersInAssemblyAttribute.cs
new file mode 100644
index 000000000..66e1380a0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAllTypesAndMembersInAssemblyAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)]
+ public class KeptAllTypesAndMembersInAssemblyAttribute : BaseInAssemblyAttribute {
+ public KeptAllTypesAndMembersInAssemblyAttribute (string assemblyFileName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAssemblyAttribute.cs
new file mode 100644
index 000000000..5107bdef2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAssemblyAttribute.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ /// <summary>
+ /// Verifies that an assembly does exist in the output directory
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)]
+ public class KeptAssemblyAttribute : KeptAttribute {
+
+ public KeptAssemblyAttribute (string fileName)
+ {
+ if (string.IsNullOrEmpty (fileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (fileName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttribute.cs
new file mode 100644
index 000000000..837c97152
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.All, Inherited = false)]
+ public class KeptAttribute : BaseExpectedLinkedBehaviorAttribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeAttribute.cs
new file mode 100644
index 000000000..c09982a5a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeAttribute.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ [AttributeUsage (AttributeTargets.All, AllowMultiple = true, Inherited = false)]
+ public class KeptAttributeAttribute : KeptAttribute
+ {
+
+ public KeptAttributeAttribute (string attributeName)
+ {
+ if (string.IsNullOrEmpty (attributeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (attributeName));
+ }
+
+ public KeptAttributeAttribute (Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeInAssemblyAttribute.cs
new file mode 100644
index 000000000..266d8aae7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeInAssemblyAttribute.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class KeptAttributeInAssemblyAttribute : BaseInAssemblyAttribute {
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on an assembly
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeTypeName"></param>
+ public KeptAttributeInAssemblyAttribute (string assemblyName, string attributeTypeName)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on an assembly
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeType"></param>
+ public KeptAttributeInAssemblyAttribute (string assemblyName, Type attributeType)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on a specific type
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeTypeName"></param>
+ /// <param name="onType"></param>
+ public KeptAttributeInAssemblyAttribute (string assemblyName, string attributeTypeName, string onType)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on a specific type
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeType"></param>
+ /// <param name="onType"></param>
+ public KeptAttributeInAssemblyAttribute (string assemblyName, Type attributeType, Type onType)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on a member in a specific type
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeTypeName"></param>
+ /// <param name="onType"></param>
+ /// <param name="member"></param>
+ public KeptAttributeInAssemblyAttribute (string assemblyName, string attributeTypeName, string onType, string member)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on a member in a specific type
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeType"></param>
+ /// <param name="onType"></param>
+ /// <param name="member"></param>
+ public KeptAttributeInAssemblyAttribute (string assemblyName, Type attributeType, Type onType, string member)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeOnFixedBufferTypeAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeOnFixedBufferTypeAttribute.cs
new file mode 100644
index 000000000..91145dae1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeOnFixedBufferTypeAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
+ public class KeptAttributeOnFixedBufferTypeAttribute : KeptAttribute {
+ public KeptAttributeOnFixedBufferTypeAttribute (string attributeName)
+ {
+ if (string.IsNullOrEmpty (attributeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (attributeName));
+ }
+
+ public KeptAttributeOnFixedBufferTypeAttribute (Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBackingFieldAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBackingFieldAttribute.cs
new file mode 100644
index 000000000..b21ce0628
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBackingFieldAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Event, AllowMultiple = false, Inherited = false)]
+ public sealed class KeptBackingFieldAttribute : KeptAttribute {
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseOnTypeInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseOnTypeInAssemblyAttribute.cs
new file mode 100644
index 000000000..2d3e74956
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseOnTypeInAssemblyAttribute.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class KeptBaseOnTypeInAssemblyAttribute : BaseInAssemblyAttribute {
+ public KeptBaseOnTypeInAssemblyAttribute (string assemblyFileName, Type type, string baseAssemblyFileName, Type baseType)
+ {
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+
+ if (string.IsNullOrEmpty (baseAssemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (baseAssemblyFileName));
+ if (baseType == null)
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (baseType));
+ }
+
+ public KeptBaseOnTypeInAssemblyAttribute (string assemblyFileName, string typeName, string baseAssemblyFileName, string baseTypeName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ if (string.IsNullOrEmpty (typeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName));
+
+ if (string.IsNullOrEmpty (baseAssemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (baseAssemblyFileName));
+ if (string.IsNullOrEmpty (baseTypeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (baseTypeName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseTypeAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseTypeAttribute.cs
new file mode 100644
index 000000000..0d2f33988
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseTypeAttribute.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum, AllowMultiple = false, Inherited = false)]
+ public sealed class KeptBaseTypeAttribute : KeptAttribute
+ {
+ public KeptBaseTypeAttribute (Type baseType)
+ {
+ if (baseType == null)
+ throw new ArgumentNullException (nameof (baseType));
+ }
+
+ public KeptBaseTypeAttribute (Type baseType, params object[] typeArguments)
+ {
+ if (baseType == null)
+ throw new ArgumentNullException (nameof (baseType));
+ if (typeArguments == null)
+ throw new ArgumentNullException (nameof (typeArguments));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs
new file mode 100644
index 000000000..79d7a6f07
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)]
+ public class KeptDelegateCacheFieldAttribute : KeptAttribute {
+ public KeptDelegateCacheFieldAttribute (string uniquePartOfName)
+ {
+ if (string.IsNullOrEmpty (uniquePartOfName))
+ throw new ArgumentNullException (nameof (uniquePartOfName));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventAddMethodAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventAddMethodAttribute.cs
new file mode 100644
index 000000000..34e65d4ea
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventAddMethodAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Event, Inherited = false, AllowMultiple = false)]
+ public class KeptEventAddMethodAttribute : KeptAttribute {
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventRemoveMethodAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventRemoveMethodAttribute.cs
new file mode 100644
index 000000000..d64cf9b38
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventRemoveMethodAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Event, Inherited = false, AllowMultiple = false)]
+ public class KeptEventRemoveMethodAttribute : KeptAttribute {
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptFixedBufferAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptFixedBufferAttribute.cs
new file mode 100644
index 000000000..5b5879699
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptFixedBufferAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
+ public class KeptFixedBufferAttribute : KeptAttribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInitializerData.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInitializerData.cs
new file mode 100644
index 000000000..c0ce6ef0b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInitializerData.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
+ public class KeptInitializerData : KeptAttribute {
+
+ public KeptInitializerData ()
+ {
+ }
+
+ public KeptInitializerData (int occuranceIndexInBody)
+ {
+ if (occuranceIndexInBody < 0)
+ throw new ArgumentException ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceAttribute.cs
new file mode 100644
index 000000000..da701a184
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
+ public class KeptInterfaceAttribute : KeptAttribute
+ {
+
+ public KeptInterfaceAttribute (Type interfaceType)
+ {
+ if (interfaceType == null)
+ throw new ArgumentNullException (nameof (interfaceType));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceOnTypeInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceOnTypeInAssemblyAttribute.cs
new file mode 100644
index 000000000..bcbf6744a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceOnTypeInAssemblyAttribute.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class KeptInterfaceOnTypeInAssemblyAttribute : BaseInAssemblyAttribute {
+ public KeptInterfaceOnTypeInAssemblyAttribute (string assemblyFileName, Type type, string interfaceAssemblyFileName, Type interfaceType)
+ {
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+
+ if (string.IsNullOrEmpty (interfaceAssemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceAssemblyFileName));
+ if (interfaceType == null)
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceType));
+ }
+
+ public KeptInterfaceOnTypeInAssemblyAttribute (string assemblyFileName, string typeName, string interfaceAssemblyFileName, string interfaceTypeName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ if (string.IsNullOrEmpty (typeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName));
+
+ if (string.IsNullOrEmpty (interfaceAssemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceAssemblyFileName));
+ if (string.IsNullOrEmpty (interfaceTypeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceTypeName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberAttribute.cs
new file mode 100644
index 000000000..6c9d1bfdd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberAttribute.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true, Inherited = false)]
+ public sealed class KeptMemberAttribute : KeptAttribute {
+
+ public KeptMemberAttribute (string name)
+ {
+ if (string.IsNullOrEmpty (name))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (name));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberInAssemblyAttribute.cs
new file mode 100644
index 000000000..fed2061ea
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberInAssemblyAttribute.cs
@@ -0,0 +1,28 @@
+using System;
+
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)]
+ public class KeptMemberInAssemblyAttribute : BaseInAssemblyAttribute {
+
+ public KeptMemberInAssemblyAttribute (string assemblyFileName, Type type, params string [] memberNames)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentNullException (nameof (assemblyFileName));
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ if (memberNames == null)
+ throw new ArgumentNullException (nameof (memberNames));
+ }
+
+ public KeptMemberInAssemblyAttribute (string assemblyFileName, string typeName, params string [] memberNames)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentNullException (nameof (assemblyFileName));
+ if (typeName == null)
+ throw new ArgumentNullException (nameof (typeName));
+ if (memberNames == null)
+ throw new ArgumentNullException (nameof (memberNames));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferenceAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferenceAttribute.cs
new file mode 100644
index 000000000..4ca94624a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferenceAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ /// <summary>
+ /// Verifies that a reference exists in the test case assembly
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class KeptReferenceAttribute : KeptAttribute {
+ public KeptReferenceAttribute (string name)
+ {
+ if (string.IsNullOrEmpty (name))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (name));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferencesInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferencesInAssemblyAttribute.cs
new file mode 100644
index 000000000..f83a67c3e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferencesInAssemblyAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class KeptReferencesInAssemblyAttribute : BaseInAssemblyAttribute {
+ public KeptReferencesInAssemblyAttribute (string assemblyFileName, string [] expectedReferenceAssemblyNames)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentNullException (nameof (assemblyFileName));
+
+ if (expectedReferenceAssemblyNames == null)
+ throw new ArgumentNullException (nameof (expectedReferenceAssemblyNames));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceAttribute.cs
new file mode 100644
index 000000000..0106dfd1a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ /// <summary>
+ /// Verifies that a resource exists in the test case assembly
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class KeptResourceAttribute : KeptAttribute {
+ public KeptResourceAttribute (string name)
+ {
+ if (string.IsNullOrEmpty (name))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (name));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceInAssemblyAttribute.cs
new file mode 100644
index 000000000..c17fed964
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceInAssemblyAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ /// <summary>
+ /// Verifies that an embedded resource exists in an assembly
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class KeptResourceInAssemblyAttribute : BaseInAssemblyAttribute {
+ public KeptResourceInAssemblyAttribute (string assemblyFileName, string resourceName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentNullException (nameof (assemblyFileName));
+
+ if (string.IsNullOrEmpty (resourceName))
+ throw new ArgumentNullException (nameof (resourceName));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSecurityAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSecurityAttribute.cs
new file mode 100644
index 000000000..e25905630
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSecurityAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
+ public class KeptSecurityAttribute : KeptAttribute {
+ public KeptSecurityAttribute (string attributeName)
+ {
+ if (string.IsNullOrEmpty (attributeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (attributeName));
+ }
+
+ public KeptSecurityAttribute (Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSymbolsAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSymbolsAttribute.cs
new file mode 100644
index 000000000..897c0b3fa
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSymbolsAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class KeptSymbolsAttribute : KeptAttribute {
+ public KeptSymbolsAttribute (string assemblyFileName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptTypeInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptTypeInAssemblyAttribute.cs
new file mode 100644
index 000000000..b5aee1392
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptTypeInAssemblyAttribute.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)]
+ public class KeptTypeInAssemblyAttribute : BaseInAssemblyAttribute {
+ public KeptTypeInAssemblyAttribute (string assemblyFileName, Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ }
+
+ public KeptTypeInAssemblyAttribute (string assemblyFileName, string typeName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ if (string.IsNullOrEmpty (typeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyAttribute.cs
new file mode 100644
index 000000000..60cab2a3f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyAttribute.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ /// <summary>
+ /// Verifies that an assembly does not exist in the output directory
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)]
+ public class RemovedAssemblyAttribute : BaseExpectedLinkedBehaviorAttribute {
+
+ public RemovedAssemblyAttribute (string fileName)
+ {
+ if (string.IsNullOrEmpty (fileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (fileName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAttributeInAssembly.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAttributeInAssembly.cs
new file mode 100644
index 000000000..b418357ad
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAttributeInAssembly.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class RemovedAttributeInAssembly : BaseInAssemblyAttribute {
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on an assembly
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeTypeName"></param>
+ public RemovedAttributeInAssembly (string assemblyName, string attributeTypeName)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on an assembly
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeType"></param>
+ public RemovedAttributeInAssembly (string assemblyName, Type attributeType)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on a specific type
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeTypeName"></param>
+ /// <param name="onType"></param>
+ public RemovedAttributeInAssembly (string assemblyName, string attributeTypeName, string onType)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on a specific type
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeType"></param>
+ /// <param name="onType"></param>
+ public RemovedAttributeInAssembly (string assemblyName, Type attributeType, Type onType)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on a member in a specific type
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeTypeName"></param>
+ /// <param name="onType"></param>
+ /// <param name="member"></param>
+ public RemovedAttributeInAssembly (string assemblyName, string attributeTypeName, string onType, string member)
+ {
+ }
+
+ /// <summary>
+ /// Asserts a CustomAttribute was kept on a member in a specific type
+ /// </summary>
+ /// <param name="assemblyName"></param>
+ /// <param name="attributeType"></param>
+ /// <param name="onType"></param>
+ /// <param name="member"></param>
+ public RemovedAttributeInAssembly (string assemblyName, Type attributeType, Type onType, string member)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedForwarderAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedForwarderAttribute.cs
new file mode 100644
index 000000000..645a01bdc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedForwarderAttribute.cs
@@ -0,0 +1,15 @@
+using System;
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class RemovedForwarderAttribute : BaseInAssemblyAttribute
+ {
+ public RemovedForwarderAttribute (string assemblyFileName, string typeName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ if (string.IsNullOrEmpty (typeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedInterfaceOnTypeInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedInterfaceOnTypeInAssemblyAttribute.cs
new file mode 100644
index 000000000..169a0cc95
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedInterfaceOnTypeInAssemblyAttribute.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class RemovedInterfaceOnTypeInAssemblyAttribute : BaseInAssemblyAttribute {
+ public RemovedInterfaceOnTypeInAssemblyAttribute (string assemblyFileName, Type type, string interfaceAssemblyFileName, Type interfaceType)
+ {
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+
+ if (string.IsNullOrEmpty (interfaceAssemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceAssemblyFileName));
+ if (interfaceType == null)
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceType));
+ }
+
+ public RemovedInterfaceOnTypeInAssemblyAttribute (string assemblyFileName, string typeName, string interfaceAssemblyFileName, string interfaceTypeName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ if (string.IsNullOrEmpty (typeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName));
+
+ if (string.IsNullOrEmpty (interfaceAssemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceAssemblyFileName));
+ if (string.IsNullOrEmpty (interfaceTypeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceTypeName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedMemberInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedMemberInAssemblyAttribute.cs
new file mode 100644
index 000000000..36bc435bf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedMemberInAssemblyAttribute.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)]
+ public class RemovedMemberInAssemblyAttribute : BaseInAssemblyAttribute {
+
+ public RemovedMemberInAssemblyAttribute (string assemblyFileName, Type type, params string [] memberNames)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentNullException (nameof (assemblyFileName));
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ if (memberNames == null)
+ throw new ArgumentNullException (nameof (memberNames));
+ }
+
+ public RemovedMemberInAssemblyAttribute (string assemblyFileName, string typeName, params string [] memberNames)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentNullException (nameof (assemblyFileName));
+ if (typeName == null)
+ throw new ArgumentNullException (nameof (typeName));
+ if (memberNames == null)
+ throw new ArgumentNullException (nameof (memberNames));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedPseudoAttributeAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedPseudoAttributeAttribute.cs
new file mode 100644
index 000000000..3a95bfa0d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedPseudoAttributeAttribute.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Interface | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event, AllowMultiple = true, Inherited = false)]
+ public class RemovedPseudoAttributeAttribute : BaseExpectedLinkedBehaviorAttribute {
+ public RemovedPseudoAttributeAttribute (uint value) {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedResourceInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedResourceInAssemblyAttribute.cs
new file mode 100644
index 000000000..e05b7ed80
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedResourceInAssemblyAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ /// <summary>
+ /// Verifies that an embedded resource was removed from an assembly
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class RemovedResourceInAssemblyAttribute : BaseInAssemblyAttribute {
+ public RemovedResourceInAssemblyAttribute (string assemblyFileName, string resourceName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentNullException (nameof (assemblyFileName));
+
+ if (string.IsNullOrEmpty (resourceName))
+ throw new ArgumentNullException (nameof (resourceName));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedSymbolsAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedSymbolsAttribute.cs
new file mode 100644
index 000000000..633617245
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedSymbolsAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+ public class RemovedSymbolsAttribute : BaseExpectedLinkedBehaviorAttribute {
+ public RemovedSymbolsAttribute (string assemblyFileName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedTypeInAssemblyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedTypeInAssemblyAttribute.cs
new file mode 100644
index 000000000..253f5bed2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedTypeInAssemblyAttribute.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions
+{
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)]
+ public class RemovedTypeInAssemblyAttribute : BaseInAssemblyAttribute {
+ public RemovedTypeInAssemblyAttribute (string assemblyFileName, Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException (nameof (type));
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ }
+
+ public RemovedTypeInAssemblyAttribute (string assemblyFileName, string typeName)
+ {
+ if (string.IsNullOrEmpty (assemblyFileName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName));
+ if (string.IsNullOrEmpty (typeName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs
new file mode 100644
index 000000000..eaccabd25
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Assertions {
+
+ public enum SkipPeVerifyForToolchian
+ {
+ Pedump
+ }
+
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SkipPeVerifyAttribute : BaseExpectedLinkedBehaviorAttribute
+ {
+ public SkipPeVerifyAttribute ()
+ {
+ }
+
+ public SkipPeVerifyAttribute (SkipPeVerifyForToolchian toolchain)
+ {
+ }
+
+ public SkipPeVerifyAttribute (string assemblyName)
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/BaseMetadataAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/BaseMetadataAttribute.cs
new file mode 100644
index 000000000..d98584eab
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/BaseMetadataAttribute.cs
@@ -0,0 +1,9 @@
+using System;
+using System.Diagnostics;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata
+{
+ [Conditional("INCLUDE_EXPECTATIONS")]
+ public abstract class BaseMetadataAttribute : Attribute {
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/DefineAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/DefineAttribute.cs
new file mode 100644
index 000000000..14e95fd4d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/DefineAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class DefineAttribute : BaseMetadataAttribute {
+ public DefineAttribute (string name)
+ {
+ if (string.IsNullOrEmpty (name))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (name));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/Il8nAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/Il8nAttribute.cs
new file mode 100644
index 000000000..e72692411
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/Il8nAttribute.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class)]
+ public sealed class Il8nAttribute : BaseMetadataAttribute {
+ public readonly string Value;
+
+ public Il8nAttribute (string value)
+ {
+ Value = value;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/IncludeBlacklistStepAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/IncludeBlacklistStepAttribute.cs
new file mode 100644
index 000000000..4144abcf6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/IncludeBlacklistStepAttribute.cs
@@ -0,0 +1,10 @@
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ public sealed class IncludeBlacklistStepAttribute : BaseMetadataAttribute {
+ public readonly bool Value;
+
+ public IncludeBlacklistStepAttribute (bool value)
+ {
+ Value = value;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/KeepTypeForwarderOnlyAssembliesAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/KeepTypeForwarderOnlyAssembliesAttribute.cs
new file mode 100644
index 000000000..ef00ca5f5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/KeepTypeForwarderOnlyAssembliesAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class)]
+ public sealed class KeepTypeForwarderOnlyAssembliesAttribute : BaseMetadataAttribute {
+ public KeepTypeForwarderOnlyAssembliesAttribute (string value)
+ {
+ if (string.IsNullOrEmpty (value))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (value));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/NotATestCaseAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/NotATestCaseAttribute.cs
new file mode 100644
index 000000000..1fabca331
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/NotATestCaseAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct)]
+ public class NotATestCaseAttribute : BaseMetadataAttribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceAttribute.cs
new file mode 100644
index 000000000..0c6fa852d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceAttribute.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class ReferenceAttribute : BaseMetadataAttribute {
+
+ public ReferenceAttribute (string value)
+ {
+ if (string.IsNullOrEmpty (value))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (value));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceDependencyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceDependencyAttribute.cs
new file mode 100644
index 000000000..9d536a33e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceDependencyAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class ReferenceDependencyAttribute : BaseMetadataAttribute {
+ public ReferenceDependencyAttribute (string value)
+ {
+ if (string.IsNullOrEmpty (value))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (value));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SandboxDependencyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SandboxDependencyAttribute.cs
new file mode 100644
index 000000000..b51755dca
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SandboxDependencyAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SandboxDependencyAttribute : BaseMetadataAttribute {
+
+ public SandboxDependencyAttribute (string relativePathToFile, string destinationFileName = null)
+ {
+ if (string.IsNullOrEmpty (relativePathToFile))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (relativePathToFile));
+ }
+
+ public SandboxDependencyAttribute (Type typeOfSourceFileToInclude, string destinationFileName = null)
+ {
+ if (typeOfSourceFileToInclude == null)
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (typeOfSourceFileToInclude));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCSharpCompilerToUseAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCSharpCompilerToUseAttribute.cs
new file mode 100644
index 000000000..0e86a36de
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCSharpCompilerToUseAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)]
+ public class SetupCSharpCompilerToUseAttribute : BaseMetadataAttribute {
+ public SetupCSharpCompilerToUseAttribute (string name)
+ {
+ if (string.IsNullOrEmpty (name))
+ throw new ArgumentNullException (nameof (name));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAfterAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAfterAttribute.cs
new file mode 100644
index 000000000..dbaddb631
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAfterAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ /// <summary>
+ /// Use to compile an assembly after compiling the main test case executabe
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SetupCompileAfterAttribute : BaseMetadataAttribute {
+ public SetupCompileAfterAttribute (string outputName, string[] sourceFiles, string[] references = null, string[] defines = null, string[] resources = null, string additionalArguments = null, string compilerToUse = null)
+ {
+ if (sourceFiles == null)
+ throw new ArgumentNullException (nameof (sourceFiles));
+
+ if (string.IsNullOrEmpty (outputName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (outputName));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileArgumentAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileArgumentAttribute.cs
new file mode 100644
index 000000000..bec6d93c1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileArgumentAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SetupCompileArgumentAttribute : BaseMetadataAttribute {
+ public SetupCompileArgumentAttribute (string value)
+ {
+ if (string.IsNullOrEmpty (value))
+ throw new ArgumentNullException (nameof(value));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAsLibraryAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAsLibraryAttribute.cs
new file mode 100644
index 000000000..1ca047cbd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAsLibraryAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)]
+ public class SetupCompileAsLibraryAttribute : BaseMetadataAttribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAssemblyNameAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAssemblyNameAttribute.cs
new file mode 100644
index 000000000..ceb0842eb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAssemblyNameAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)]
+ public class SetupCompileAssemblyNameAttribute : BaseMetadataAttribute {
+ public SetupCompileAssemblyNameAttribute (string outputName)
+ {
+ if (string.IsNullOrEmpty (outputName))
+ throw new ArgumentNullException (nameof (outputName));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs
new file mode 100644
index 000000000..6b81b6681
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ /// <summary>
+ /// Use to compile an assembly before compiling the main test case executabe
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SetupCompileBeforeAttribute : BaseMetadataAttribute {
+ public SetupCompileBeforeAttribute (string outputName, string[] sourceFiles, string[] references = null, string[] defines = null, string[] resources = null, string additionalArguments = null, string compilerToUse = null, bool addAsReference = true)
+ {
+ if (sourceFiles == null)
+ throw new ArgumentNullException (nameof (sourceFiles));
+
+ if (string.IsNullOrEmpty (outputName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (outputName));
+ }
+
+ public SetupCompileBeforeAttribute (string outputName, Type[] typesToIncludeSourceFor, string[] references = null, string[] defines = null, string[] resources = null, string additionalArguments = null, string compilerToUse = null, bool addAsReference = true)
+ {
+ if (typesToIncludeSourceFor == null)
+ throw new ArgumentNullException (nameof (typesToIncludeSourceFor));
+
+ if (string.IsNullOrEmpty (outputName))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (outputName));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileResourceAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileResourceAttribute.cs
new file mode 100644
index 000000000..b86a162c5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileResourceAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SetupCompileResourceAttribute : BaseMetadataAttribute {
+ public SetupCompileResourceAttribute (string relativePathToFile, string destinationFileName = null)
+ {
+ if (string.IsNullOrEmpty (relativePathToFile))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (relativePathToFile));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerActionAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerActionAttribute.cs
new file mode 100644
index 000000000..5927ba734
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerActionAttribute.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata
+{
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SetupLinkerActionAttribute : BaseMetadataAttribute
+ {
+ public SetupLinkerActionAttribute (string action, string assembly)
+ {
+ if (string.IsNullOrEmpty (action))
+ throw new ArgumentNullException (nameof (action));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerArgumentAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerArgumentAttribute.cs
new file mode 100644
index 000000000..2eb5a7f49
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerArgumentAttribute.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+
+ /// <summary>
+ /// Used to define arguments to pass to the linker.
+ ///
+ /// Don't use this attribute to setup single character flags. These flags do a poor job of communicating their purpose
+ /// and although we need to continue to support the usages that exist today, that doesn't mean we need to make our tests harder to read
+ /// </summary>
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SetupLinkerArgumentAttribute : BaseMetadataAttribute {
+ public SetupLinkerArgumentAttribute (string flag, params string [] values)
+ {
+ if (string.IsNullOrEmpty (flag))
+ throw new ArgumentNullException (nameof (flag));
+
+ if (flag[0] == '-' && flag.Length == 2) {
+ string errorMessage = "Flag `" + flag + "` is short.";
+ errorMessage += " Avoid using this attribute with command line flags that are to short to communicate their meaning. Support a more descriptive flag or create a new attribute for tests to use similar to " + nameof (SetupLinkerCoreActionAttribute);
+ throw new ArgumentException (errorMessage);
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerCoreActionAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerCoreActionAttribute.cs
new file mode 100644
index 000000000..077dad672
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerCoreActionAttribute.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata
+{
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)]
+ public class SetupLinkerCoreActionAttribute : BaseMetadataAttribute
+ {
+ public SetupLinkerCoreActionAttribute (string action)
+ {
+ if (string.IsNullOrEmpty (action))
+ throw new ArgumentNullException (nameof (action));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerKeepDebugMembersAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerKeepDebugMembersAttribute.cs
new file mode 100644
index 000000000..9fa23957a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerKeepDebugMembersAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class)]
+ public class SetupLinkerKeepDebugMembersAttribute : BaseMetadataAttribute{
+ public SetupLinkerKeepDebugMembersAttribute (string value)
+ {
+ if (string.IsNullOrEmpty (value))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (value));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkPublicAndFamilyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkPublicAndFamilyAttribute.cs
new file mode 100644
index 000000000..d3f3d7091
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkPublicAndFamilyAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)]
+ public class SetupLinkerLinkPublicAndFamilyAttribute : BaseMetadataAttribute {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkSymbolsAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkSymbolsAttribute.cs
new file mode 100644
index 000000000..3bcef8610
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkSymbolsAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class)]
+ public class SetupLinkerLinkSymbolsAttribute : BaseMetadataAttribute {
+ public SetupLinkerLinkSymbolsAttribute (string value)
+ {
+ if (string.IsNullOrEmpty (value))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (value));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerResponseFileAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerResponseFileAttribute.cs
new file mode 100644
index 000000000..8ae909446
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerResponseFileAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+ public class SetupLinkerResponseFileAttribute : BaseMetadataAttribute {
+ public SetupLinkerResponseFileAttribute(string relativePathToFile, string destinationFileName = null)
+ {
+ if (string.IsNullOrEmpty (relativePathToFile))
+ throw new ArgumentException ("Value cannot be null or empty.", nameof (relativePathToFile));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerUserActionAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerUserActionAttribute.cs
new file mode 100644
index 000000000..6185bbbf5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerUserActionAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)]
+ public class SetupLinkerUserActionAttribute : BaseMetadataAttribute {
+ public SetupLinkerUserActionAttribute (string action)
+ {
+ if (string.IsNullOrEmpty (action))
+ throw new ArgumentNullException (nameof (action));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SkipUnresolvedAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SkipUnresolvedAttribute.cs
new file mode 100644
index 000000000..bee9a7f4f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/SkipUnresolvedAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ public sealed class SkipUnresolvedAttribute : BaseMetadataAttribute {
+ public readonly bool Value;
+
+ public SkipUnresolvedAttribute (bool value)
+ {
+ Value = value;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Metadata/StripResourcesAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/StripResourcesAttribute.cs
new file mode 100644
index 000000000..97a77fb42
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Metadata/StripResourcesAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Expectations.Metadata {
+ public sealed class StripResourcesAttribute : BaseMetadataAttribute {
+ public readonly bool Value;
+
+ public StripResourcesAttribute (bool value)
+ {
+ Value = value;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj b/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj
new file mode 100644
index 000000000..73180a504
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{2C26601F-3E2F-45B9-A02F-58EE9296E19E}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Mono.Linker.Tests.Cases.Expectations</RootNamespace>
+ <AssemblyName>Mono.Linker.Tests.Cases.Expectations</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Assertions\BaseInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\ExpectBodyModifiedAttribute.cs" />
+ <Compile Include="Assertions\ExpectedExceptionHandlerSequenceAttribute.cs" />
+ <Compile Include="Assertions\ExpectedInstructionSequenceAttribute.cs" />
+ <Compile Include="Assertions\ExpectedLocalsSequenceAttribute.cs" />
+ <Compile Include="Assertions\ExpectExceptionHandlersModifiedAttribute.cs" />
+ <Compile Include="Assertions\ExpectLocalsModifiedAttribute.cs" />
+ <Compile Include="Assertions\IgnoreTestCaseAttribute.cs" />
+ <Compile Include="Assertions\KeptAllTypesAndMembersInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\KeptAssemblyAttribute.cs" />
+ <Compile Include="Assertions\KeptAttribute.cs" />
+ <Compile Include="Assertions\BaseExpectedLinkedBehaviorAttribute.cs" />
+ <Compile Include="Assertions\KeptAttributeInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\KeptAttributeOnFixedBufferTypeAttribute.cs" />
+ <Compile Include="Assertions\KeptBackingFieldAttribute.cs" />
+ <Compile Include="Assertions\KeptBaseOnTypeInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\KeptDelegateCacheFieldAttribute.cs" />
+ <Compile Include="Assertions\KeptEventAddMethodAttribute.cs" />
+ <Compile Include="Assertions\KeptEventRemoveMethodAttribute.cs" />
+ <Compile Include="Assertions\KeptFixedBufferAttribute.cs" />
+ <Compile Include="Assertions\KeptInitializerData.cs" />
+ <Compile Include="Assertions\KeptInterfaceOnTypeInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\KeptMemberAttribute.cs" />
+ <Compile Include="Assertions\KeptMemberInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\KeptReferenceAttribute.cs" />
+ <Compile Include="Assertions\KeptReferencesInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\KeptResourceAttribute.cs" />
+ <Compile Include="Assertions\KeptResourceInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\KeptSecurityAttribute.cs" />
+ <Compile Include="Assertions\KeptSymbolsAttribute.cs" />
+ <Compile Include="Assertions\KeptTypeInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\RemovedAssemblyAttribute.cs" />
+ <Compile Include="Assertions\RemovedAttributeInAssembly.cs" />
+ <Compile Include="Assertions\RemovedInterfaceOnTypeInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\RemovedMemberInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\RemovedPseudoAttributeAttribute.cs" />
+ <Compile Include="Assertions\RemovedResourceInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\RemovedSymbolsAttribute.cs" />
+ <Compile Include="Assertions\RemovedTypeInAssemblyAttribute.cs" />
+ <Compile Include="Assertions\SkipPeVerifyAttribute.cs" />
+ <Compile Include="Metadata\BaseMetadataAttribute.cs" />
+ <Compile Include="Metadata\ReferenceDependencyAttribute.cs" />
+ <Compile Include="Metadata\SetupCompileAfterAttribute.cs" />
+ <Compile Include="Metadata\SetupCompileAsLibraryAttribute.cs" />
+ <Compile Include="Metadata\SetupCompileAssemblyNameAttribute.cs" />
+ <Compile Include="Metadata\SetupCompileArgumentAttribute.cs" />
+ <Compile Include="Metadata\SetupCompileBeforeAttribute.cs" />
+ <Compile Include="Metadata\DefineAttribute.cs" />
+ <Compile Include="Metadata\IncludeBlacklistStepAttribute.cs" />
+ <Compile Include="Metadata\Il8nAttribute.cs" />
+ <Compile Include="Metadata\KeepTypeForwarderOnlyAssembliesAttribute.cs" />
+ <Compile Include="Metadata\NotATestCaseAttribute.cs" />
+ <Compile Include="Metadata\ReferenceAttribute.cs" />
+ <Compile Include="Metadata\SandboxDependencyAttribute.cs" />
+ <Compile Include="Metadata\SetupLinkerKeepDebugMembersAttribute.cs" />
+ <Compile Include="Metadata\SetupLinkerLinkPublicAndFamilyAttribute.cs" />
+ <Compile Include="Metadata\SetupLinkerResponseFileAttribute.cs" />
+ <Compile Include="Metadata\SetupLinkerUserActionAttribute.cs" />
+ <Compile Include="Metadata\SkipUnresolvedAttribute.cs" />
+ <Compile Include="Metadata\StripResourcesAttribute.cs" />
+ <Compile Include="Assertions\KeptBaseTypeAttribute.cs" />
+ <Compile Include="Assertions\KeptInterfaceAttribute.cs" />
+ <Compile Include="Assertions\KeptAttributeAttribute.cs" />
+ <Compile Include="Assertions\RemovedForwarderAttribute.cs" />
+ <Compile Include="Metadata\SetupCSharpCompilerToUseAttribute.cs" />
+ <Compile Include="Metadata\SetupLinkerActionAttribute.cs" />
+ <Compile Include="Metadata\SetupLinkerArgumentAttribute.cs" />
+ <Compile Include="Metadata\SetupLinkerCoreActionAttribute.cs" />
+ <Compile Include="Metadata\SetupCompileResourceAttribute.cs" />
+ <Compile Include="Metadata\SetupLinkerLinkSymbolsAttribute.cs" />
+ <Compile Include="Support\PreserveDependencyAttribute.cs" />
+ <Compile Include="Assertions\AddedPseudoAttributeAttribute.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases.Expectations/Support/PreserveDependencyAttribute.cs b/test/Mono.Linker.Tests.Cases.Expectations/Support/PreserveDependencyAttribute.cs
new file mode 100644
index 000000000..e457fa3ce
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases.Expectations/Support/PreserveDependencyAttribute.cs
@@ -0,0 +1,46 @@
+//
+// PreserveDependencyAttribute.cs
+//
+// Authors:
+// Marek Safar <marek.safar@gmail.com>
+//
+// Copyright (C) 2018 Microsoft Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+namespace System.Runtime.CompilerServices {
+ [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Field, AllowMultiple = true)]
+ public sealed class PreserveDependencyAttribute : Attribute {
+ public PreserveDependencyAttribute (string memberSignature)
+ {
+ }
+
+ public PreserveDependencyAttribute (string memberSignature, string typeName)
+ {
+ }
+
+ public PreserveDependencyAttribute (string memberSignature, string typeName, string assembly)
+ {
+ }
+
+ public string Condition { get; set; }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Advanced/DeadCodeElimination1.cs b/test/Mono.Linker.Tests.Cases/Advanced/DeadCodeElimination1.cs
new file mode 100644
index 000000000..339d223b6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Advanced/DeadCodeElimination1.cs
@@ -0,0 +1,19 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Advanced {
+ [IgnoreTestCase ("We cannot do this yet")]
+ class DeadCodeElimination1 {
+ public static void Main ()
+ {
+ object o = null;
+ if (o is B)
+ ((B) o).Method ();
+ }
+
+ class B {
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Advanced/FieldThatOnlyGetsSetIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Advanced/FieldThatOnlyGetsSetIsRemoved.cs
new file mode 100644
index 000000000..8c4933ad2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Advanced/FieldThatOnlyGetsSetIsRemoved.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Advanced {
+ [IgnoreTestCase ("We cannot do this yet")]
+ class FieldThatOnlyGetsSetIsRemoved {
+ public static void Main ()
+ {
+ new B ().Method ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ public int _unused = 3;
+
+ [Kept]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs
new file mode 100644
index 000000000..795570cf6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs
@@ -0,0 +1,33 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+[assembly: DebuggerDisplay ("{Property}", Target = typeof (DebuggerDisplayAttributeOnAssemblyUsingTarget.Foo))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("false")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), "set_Target(System.Type)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTarget {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class Foo {
+ [Kept]
+ [KeptBackingField]
+ public int Property { get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs
new file mode 100644
index 000000000..2b4c6ab50
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs
@@ -0,0 +1,25 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: DebuggerDisplay ("{Property}", Target = typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.Foo))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("false")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType {
+ public static void Main ()
+ {
+ }
+
+ public class Foo {
+ public int Property { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs
new file mode 100644
index 000000000..61db04028
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs
@@ -0,0 +1,29 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+[assembly: DebuggerDisplay ("{Property}", TargetTypeName = "Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies.DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib, library")]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("false")]
+ [SetupCompileBefore ("library.dll", new [] { typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib) })]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
+
+ [RemovedMemberInAssembly ("library.dll", typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib), "get_Property()")]
+ [KeptMemberInAssembly ("library.dll", typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib), "set_Property(System.Int32)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly {
+ public static void Main ()
+ {
+ var foo = new DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib ();
+ foo.Property = 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnType.cs
new file mode 100644
index 000000000..e52ec9e48
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnType.cs
@@ -0,0 +1,39 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("false")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ public class DebuggerDisplayAttributeOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ var bar = new Bar();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+ [DebuggerDisplay ("{Property}")]
+ class Foo {
+ public int Property { get; set; }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+ [DebuggerDisplay ("{Method()}")]
+ class Bar {
+ public int Method ()
+ {
+ return 1;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs
new file mode 100644
index 000000000..894d5adbb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs
@@ -0,0 +1,21 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("false")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ public class DebuggerDisplayAttributeOnTypeThatIsNotUsed {
+ public static void Main ()
+ {
+ }
+
+ [DebuggerDisplay ("{Property}")]
+ class Foo {
+ public int Property { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs
new file mode 100644
index 000000000..be03fde14
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs
@@ -0,0 +1,43 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute(typeof(DebuggerTypeProxyAttribute))]
+[assembly: DebuggerTypeProxy (typeof(DebuggerTypeProxyAttributeOnAssemblyUsingTarget.Foo.FooDebugView), Target = typeof (DebuggerTypeProxyAttributeOnAssemblyUsingTarget.Foo))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("false")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerTypeProxyAttribute), ".ctor(System.Type)")]
+ public class DebuggerTypeProxyAttributeOnAssemblyUsingTarget {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class Foo {
+ [Kept]
+ [KeptBackingField]
+ public int Property { get; [Kept] set; }
+
+ [Kept]
+ internal class FooDebugView
+ {
+ private Foo _foo;
+
+ public FooDebugView(Foo foo)
+ {
+ _foo = foo;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerTypeProxyAttributeOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerTypeProxyAttributeOnType.cs
new file mode 100644
index 000000000..a9db20ae7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/DebuggerTypeProxyAttributeOnType.cs
@@ -0,0 +1,33 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("false")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerTypeProxyAttribute), ".ctor(System.Type)")]
+ public class DebuggerTypeProxyAttributeOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (DebuggerTypeProxyAttribute))]
+ [DebuggerTypeProxy (typeof (FooDebugView))]
+ class Foo {
+ }
+
+ [Kept]
+ class FooDebugView {
+ public FooDebugView (Foo foo)
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs
new file mode 100644
index 000000000..4af869817
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs
@@ -0,0 +1,13 @@
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies {
+ public class DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib {
+ public int Property { get; set; }
+
+ public class NestedType {
+ public int NestedProperty { get; set; }
+ }
+
+ public class GenericType<T> {
+ public T PropertyOnGenericType { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs
new file mode 100644
index 000000000..e099dbf89
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTarget.cs
@@ -0,0 +1,33 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+[assembly: DebuggerDisplay ("{Property}", Target = typeof (DebuggerDisplayAttributeOnAssemblyUsingTarget.Foo))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), "set_Target(System.Type)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTarget {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class Foo {
+ [Kept]
+ [KeptBackingField]
+ public int Property { [Kept] get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs
new file mode 100644
index 000000000..df9ede7b2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs
@@ -0,0 +1,25 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: DebuggerDisplay ("{Property}", Target = typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.Foo))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType {
+ public static void Main ()
+ {
+ }
+
+ public class Foo {
+ public int Property { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs
new file mode 100644
index 000000000..b21c02d12
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs
@@ -0,0 +1,30 @@
+
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+[assembly: DebuggerDisplay ("{Property}", TargetTypeName = "Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies.DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib, library")]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+ [SetupCompileBefore ("library.dll", new [] { "../Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" })]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
+
+ [KeptMemberInAssembly ("library.dll", typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib), "get_Property()")]
+ [KeptMemberInAssembly ("library.dll", typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib), "set_Property(System.Int32)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly {
+ public static void Main ()
+ {
+ var foo = new DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib ();
+ foo.Property = 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs
new file mode 100644
index 000000000..4b0841ba9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs
@@ -0,0 +1,32 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+[assembly: DebuggerDisplay ("{Property}", TargetTypeName = "Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers.DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly+Foo")]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class Foo {
+ [Kept]
+ [KeptBackingField]
+ public int Property { [Kept] get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs
new file mode 100644
index 000000000..9dc27eec8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs
@@ -0,0 +1,29 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+[assembly: DebuggerDisplay ("{Property}", TargetTypeName = "Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies.DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib+GenericType`1, library")]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+ [SetupCompileBefore ("library.dll", new [] { "../Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" })]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
+
+ [KeptMemberInAssembly ("library.dll", typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.GenericType<>), "get_PropertyOnGenericType()")]
+ [KeptMemberInAssembly ("library.dll", typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.GenericType<>), "set_PropertyOnGenericType(T)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly {
+ public static void Main ()
+ {
+ var foo = new DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.GenericType<int> ();
+ foo.PropertyOnGenericType = 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs
new file mode 100644
index 000000000..44242011d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs
@@ -0,0 +1,29 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+[assembly: DebuggerDisplay ("{Property}", TargetTypeName = "Mono.Linker.Tests.Cases.Attributes.Debugger.Dependencies.DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib+NestedType, library")]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+ [SetupCompileBefore ("library.dll", new [] { "../Dependencies/DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" })]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), "set_TargetTypeName(System.String)")]
+
+ [KeptMemberInAssembly ("library.dll", typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.NestedType), "get_NestedProperty()")]
+ [KeptMemberInAssembly ("library.dll", typeof (DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.NestedType), "set_NestedProperty(System.Int32)")]
+ public class DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly {
+ public static void Main ()
+ {
+ var foo = new DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.NestedType ();
+ foo.NestedProperty = 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnType.cs
new file mode 100644
index 000000000..a68cf7e5d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnType.cs
@@ -0,0 +1,42 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerDisplayAttribute), ".ctor(System.String)")]
+ public class DebuggerDisplayAttributeOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ var bar = new Bar();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+ [DebuggerDisplay ("{Property}")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ public int Property { [Kept] get; [Kept] set; }
+ }
+
+ [Kept]
+ [KeptMember(".ctor()")]
+ [KeptAttributeAttribute (typeof (DebuggerDisplayAttribute))]
+ [DebuggerDisplay ("{Method()}")]
+ class Bar {
+ [Kept]
+ public int Method ()
+ {
+ return 1;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs
new file mode 100644
index 000000000..de51c012b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs
@@ -0,0 +1,21 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ public class DebuggerDisplayAttributeOnTypeThatIsNotUsed {
+ public static void Main ()
+ {
+ }
+
+ [DebuggerDisplay ("{Property}")]
+ class Foo {
+ public int Property { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs
new file mode 100644
index 000000000..4324bdbc7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs
@@ -0,0 +1,46 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (DebuggerTypeProxyAttribute))]
+[assembly: DebuggerTypeProxy (typeof(DebuggerTypeProxyAttributeOnAssemblyUsingTarget.Foo.FooDebugView), Target = typeof (DebuggerTypeProxyAttributeOnAssemblyUsingTarget.Foo))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerTypeProxyAttribute), ".ctor(System.Type)")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerTypeProxyAttribute), "set_Target(System.Type)")]
+ public class DebuggerTypeProxyAttributeOnAssemblyUsingTarget {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class Foo {
+ [Kept]
+ [KeptBackingField]
+ public int Property { get; [Kept] set; }
+
+ [Kept]
+ internal class FooDebugView
+ {
+ [Kept]
+ private Foo _foo;
+
+ [Kept]
+ public FooDebugView(Foo foo)
+ {
+ _foo = foo;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnType.cs
new file mode 100644
index 000000000..70351534f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.Debugger/KeepDebugMembers/DebuggerTypeProxyAttributeOnType.cs
@@ -0,0 +1,34 @@
+using System.Diagnostics;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Debugger.KeepDebugMembers {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerKeepDebugMembers ("true")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (DebuggerTypeProxyAttribute), ".ctor(System.Type)")]
+ public class DebuggerTypeProxyAttributeOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (DebuggerTypeProxyAttribute))]
+ [DebuggerTypeProxy (typeof (FooDebugView))]
+ class Foo {
+ }
+
+ [Kept]
+ class FooDebugView {
+ [Kept]
+ public FooDebugView (Foo foo)
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/AutoClass.cs b/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/AutoClass.cs
new file mode 100644
index 000000000..be4085bad
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/AutoClass.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes.StructLayout
+{
+ [StructLayout (LayoutKind.Auto)]
+ [KeptMember (".ctor()")]
+ class AutoClassData {
+ public int never_used;
+ [Kept]
+ public int used;
+ }
+
+ public class AutoClass
+ {
+ public static void Main ()
+ {
+ var c = new AutoClassData ();
+ c.used = 1;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/ExplicitClass.cs b/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/ExplicitClass.cs
new file mode 100644
index 000000000..dc9f60013
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/ExplicitClass.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes.StructLayout {
+ [StructLayout (LayoutKind.Explicit)]
+ [KeptMember (".ctor()")]
+ class ExplicitClassData {
+ [FieldOffset (0)]
+ [Kept] // the linker could remove this
+ public int never_used;
+ [FieldOffset (4)]
+ [Kept]
+ public int used;
+ [FieldOffset (8)]
+ [Kept]
+ public int never_ever_used;
+ }
+
+ public class ExplicitClass
+ {
+ public static void Main ()
+ {
+ var c = new ExplicitClassData ();
+ c.used = 1;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/SequentialClass.cs b/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/SequentialClass.cs
new file mode 100644
index 000000000..dd8a8b659
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/SequentialClass.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes.StructLayout
+{
+ [StructLayout (LayoutKind.Sequential)]
+ [KeptMember (".ctor()")]
+ class SequentialClassData
+ {
+ [Kept]
+ public int never_used;
+ [Kept]
+ public int used;
+ }
+
+ public class SequentialClass
+ {
+ public static void Main ()
+ {
+ var c = new SequentialClassData ();
+ c.used = 1;
+ if (Marshal.SizeOf (c) != 8)
+ throw new ApplicationException ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/UnusedTypeWithSequentialLayoutIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/UnusedTypeWithSequentialLayoutIsRemoved.cs
new file mode 100644
index 000000000..d3cb2c30f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes.StructLayout/UnusedTypeWithSequentialLayoutIsRemoved.cs
@@ -0,0 +1,16 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes.StructLayout
+{
+ class UnusedTypeWithSequentialLayoutIsRemoved {
+ static void Main ()
+ {
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ class B {
+ int a;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly.cs
new file mode 100644
index 000000000..1e74f81c2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly.cs
@@ -0,0 +1,16 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: AttributeInReference]
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly_Lib.cs" })]
+ [RemovedAssembly ("library.dll")]
+ class AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly {
+ static void Main ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AssemblyAttributeKeptInComplexCase.cs b/test/Mono.Linker.Tests.Cases/Attributes/AssemblyAttributeKeptInComplexCase.cs
new file mode 100644
index 000000000..9373f9bde
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AssemblyAttributeKeptInComplexCase.cs
@@ -0,0 +1,41 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes;
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+// This attribute is defined in this assembly so it will be kept
+[assembly: AssemblyAttributeKeptInComplexCase.Foo]
+
+// This attribute is not going to get marked on the first pass because the reference
+// it is defined in will not have been marked yet.
+// The catch is, Foo's ctor() will mark a method in `library`, at which point we now expect this
+// attribute to be kept
+[assembly: AssemblyAttributeKeptInComplexCase_Lib.OtherAssembly]
+
+[assembly: KeptAttributeAttribute (typeof (AssemblyAttributeKeptInComplexCase.FooAttribute))]
+[assembly: KeptAttributeAttribute (typeof (AssemblyAttributeKeptInComplexCase_Lib.OtherAssemblyAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/AssemblyAttributeKeptInComplexCase_Lib.cs" })]
+ [KeptAssembly ("library.dll")]
+ [KeptMemberInAssembly ("library.dll", typeof (AssemblyAttributeKeptInComplexCase_Lib.OtherAssemblyAttribute), ".ctor()")]
+ [KeptMemberInAssembly ("library.dll", typeof (AssemblyAttributeKeptInComplexCase_Lib), "MethodThatWillBeUsed()")]
+ public class AssemblyAttributeKeptInComplexCase {
+ static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Attribute))]
+ public class FooAttribute : Attribute {
+ [Kept]
+ public FooAttribute ()
+ {
+ // This ctor will be marked late after processing the queue
+ // This method we call will be the first marked in the referenced library
+ AssemblyAttributeKeptInComplexCase_Lib.MethodThatWillBeUsed ();
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnAssemblyIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnAssemblyIsKept.cs
new file mode 100644
index 000000000..b42d3ff2f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnAssemblyIsKept.cs
@@ -0,0 +1,22 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+[assembly: AttributeOnAssemblyIsKept.Foo]
+[assembly: KeptAttributeAttribute (typeof (AttributeOnAssemblyIsKept.FooAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ class AttributeOnAssemblyIsKept {
+ static void Main ()
+ {
+ }
+
+ [KeptBaseType (typeof (System.Attribute))]
+ public class FooAttribute : Attribute {
+ [Kept]
+ public FooAttribute ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnParameterInUsedMethodIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnParameterInUsedMethodIsKept.cs
new file mode 100644
index 000000000..01cdad565
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnParameterInUsedMethodIsKept.cs
@@ -0,0 +1,22 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ class AttributeOnParameterInUsedMethodIsKept {
+ static void Main ()
+ {
+ Method ("Bar");
+ }
+
+ [Kept]
+ static void Method ([Foo] [KeptAttributeAttribute (typeof (FooAttribute))] string arg)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof(Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeIsKept.cs
new file mode 100644
index 000000000..1cd0cdc23
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeIsKept.cs
@@ -0,0 +1,20 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [Foo]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ class AttributeOnPreservedTypeIsKept {
+ public static void Main ()
+ {
+ }
+
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ [Kept]
+ public FooAttribute ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInConstructorIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInConstructorIsKept.cs
new file mode 100644
index 000000000..aa6600837
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInConstructorIsKept.cs
@@ -0,0 +1,27 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [Foo (typeof (A))]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ class AttributeOnPreservedTypeWithTypeUsedInConstructorIsKept {
+ public static void Main ()
+ {
+ }
+
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ [Kept]
+ public FooAttribute (Type val)
+ {
+ }
+ }
+
+ [Kept]
+ class A {
+ public A ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInDifferentNamespaceIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInDifferentNamespaceIsKept.cs
new file mode 100644
index 000000000..976ac6d26
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInDifferentNamespaceIsKept.cs
@@ -0,0 +1,33 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace NamespaceForAttributeOnPreservedTypeWithTypeUsedInDifferentNamespaceIsKept {
+ [Kept]
+ class A {
+ public A ()
+ {
+ }
+ }
+}
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [Foo (typeof (NamespaceForAttributeOnPreservedTypeWithTypeUsedInDifferentNamespaceIsKept.A))]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ class AttributeOnPreservedTypeWithTypeUsedInDifferentNamespaceIsKept {
+ public static void Main ()
+ {
+ }
+
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ [Kept]
+ public FooAttribute (Type val)
+ {
+ }
+ }
+
+ // This A is not used and should be removed
+ class A {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInFieldIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInFieldIsKept.cs
new file mode 100644
index 000000000..e038333e9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInFieldIsKept.cs
@@ -0,0 +1,26 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [Foo (Val = typeof (A))]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ class AttributeOnPreservedTypeWithTypeUsedInFieldIsKept {
+ public static void Main ()
+ {
+ }
+
+ [KeptMember(".ctor()")]
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ [Kept]
+ public Type Val;
+ }
+
+ [Kept]
+ class A {
+ public A ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInPropertySetterIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInPropertySetterIsKept.cs
new file mode 100644
index 000000000..8bc4dd523
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithTypeUsedInPropertySetterIsKept.cs
@@ -0,0 +1,27 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [Foo (Val = typeof (A))]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ class AttributeOnPreservedTypeWithTypeUsedInPropertySetterIsKept {
+ public static void Main ()
+ {
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ [Kept]
+ [KeptBackingField]
+ public Type Val { get; [Kept] set; }
+ }
+
+ [Kept]
+ class A {
+ public A ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithUsedSetter.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithUsedSetter.cs
new file mode 100644
index 000000000..957de91e1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnPreservedTypeWithUsedSetter.cs
@@ -0,0 +1,20 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [Foo (Val = 1)]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ class AttributeOnPreservedTypeWithUsedSetter {
+ public static void Main ()
+ {
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ [Kept]
+ [KeptBackingField]
+ public int Val { get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedFieldIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedFieldIsKept.cs
new file mode 100644
index 000000000..834c446ac
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedFieldIsKept.cs
@@ -0,0 +1,25 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ class AttributeOnUsedFieldIsKept {
+ public static void Main ()
+ {
+ var val = new A ().field;
+ }
+
+ [KeptMember (".ctor()")]
+ class A {
+ [Kept]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ [Foo]
+ public int field;
+ }
+
+ [Kept]
+ [KeptMember(".ctor()")]
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedMethodIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedMethodIsKept.cs
new file mode 100644
index 000000000..0f99a1ca9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedMethodIsKept.cs
@@ -0,0 +1,27 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ class AttributeOnUsedMethodIsKept {
+ public static void Main ()
+ {
+ new A ().Method ();
+ }
+
+ [KeptMember (".ctor()")]
+ class A {
+ [Foo]
+ [Kept]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ public void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedPropertyIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedPropertyIsKept.cs
new file mode 100644
index 000000000..8e61c12c1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/AttributeOnUsedPropertyIsKept.cs
@@ -0,0 +1,27 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ class AttributeOnUsedPropertyIsKept {
+ public static void Main ()
+ {
+ var val = new A ().Field;
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptMember ("get_Field()")]
+ class A {
+ [Kept]
+ [KeptBackingField]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ [Foo]
+ public int Field { get; set; }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (System.Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs
new file mode 100644
index 000000000..9ec53e48a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/CoreLibraryAssemblyAttributesAreKept.cs
@@ -0,0 +1,21 @@
+using System.Reflection;
+using System.Timers;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [Reference ("System.dll")]
+ [SetupLinkerCoreAction ("link")]
+ [KeptAttributeInAssembly ("mscorlib.dll", typeof (AssemblyDescriptionAttribute))]
+ [KeptAttributeInAssembly ("mscorlib.dll", typeof (AssemblyCompanyAttribute))]
+ [KeptAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))]
+ [KeptAttributeInAssembly ("System.dll", typeof (AssemblyCompanyAttribute))]
+ [SkipPeVerify]
+ public class CoreLibraryAssemblyAttributesAreKept {
+ public static void Main ()
+ {
+ // Use something from System so that the entire reference isn't linked away
+ var system = new Timer ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs
new file mode 100644
index 000000000..f19ffcf4d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType1.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithType2.dll", new [] { typeof(TypeDefinedInReference2) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType1.dll", typeof (TypeDefinedInReference))]
+ [KeptTypeInAssembly ("LibraryWithType2.dll", typeof (TypeDefinedInReference2))]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type[])")]
+ public class OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType {
+ public static void Main()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (new [] { typeof (TypeDefinedInReference), typeof (TypeDefinedInReference2) })]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs
new file mode 100644
index 000000000..62c1fd568
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs
@@ -0,0 +1,23 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+[assembly: AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// In the case of attributes on assemblies, we expect both assemblies to be removed because we don't keep assembly level attributes
+ /// when that is the only type marked in the assembly
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [RemovedAssembly ("LibraryWithType.dll")]
+ [RemovedAssembly ("LibraryWithAttribute.dll")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly {
+ public static void Main()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs
new file mode 100644
index 000000000..65da28788
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+[assembly: KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+[assembly: AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof (AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ [KeptTypeInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference_OtherType))]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed {
+ public static void Main ()
+ {
+ // Use something in the attribute assembly so that the special behavior of not preserving a reference if the only thing that is marked
+ // are attributes is not trigged
+ AttributeDefinedInReference_OtherType.Method();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs
new file mode 100644
index 000000000..42b28839a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs
@@ -0,0 +1,44 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ [KeptDelegateCacheField ("0")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.MyEvent += FooOnMyEvent;
+ }
+
+ [Kept]
+ private static void FooOnMyEvent (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo
+ {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ [KeptAttributeAttribute (typeof( AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ public event EventHandler MyEvent;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs
new file mode 100644
index 000000000..a5b52a3de
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof (TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof (AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs
new file mode 100644
index 000000000..a6f0869b1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs
@@ -0,0 +1,34 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ public int Property { get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs
new file mode 100644
index 000000000..3be888774
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof (TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof (AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType {
+ public static void Main()
+ {
+ var foo = new Foo();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ class Foo
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs
new file mode 100644
index 000000000..b385f1919
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+[assembly: AttributeDefinedInReference (FieldType = typeof (TypeDefinedInReference))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// In the case of attributes on assemblies, we expect both assemblies to be removed because we don't keep assembly level attributes
+ /// when that is the only type marked in the assembly
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [RemovedAssembly ("LibraryWithType.dll")]
+ [RemovedAssembly ("LibraryWithAttribute.dll")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly
+ {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs
new file mode 100644
index 000000000..bba7fc8c0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs
@@ -0,0 +1,44 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
+ [KeptDelegateCacheField ("0")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.MyEvent += FooOnMyEvent;
+ }
+
+ [Kept]
+ private static void FooOnMyEvent (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (FieldType = typeof (TypeDefinedInReference))]
+ public event EventHandler MyEvent;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs
new file mode 100644
index 000000000..b8aa33f92
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs
@@ -0,0 +1,37 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod
+ {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (FieldType = typeof(TypeDefinedInReference))]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs
new file mode 100644
index 000000000..cfbefbcea
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (FieldType = typeof (TypeDefinedInReference))]
+ public int Property { get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs
new file mode 100644
index 000000000..64da808bc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (FieldType = typeof (TypeDefinedInReference))]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs
new file mode 100644
index 000000000..0ed2c3d81
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs
@@ -0,0 +1,23 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+[assembly: AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// In the case of attributes on assemblies, we expect both assemblies to be removed because we don't keep assembly level attributes
+ /// when that is the only type marked in the assembly
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [RemovedAssembly ("LibraryWithType.dll")]
+ [RemovedAssembly ("LibraryWithAttribute.dll")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs
new file mode 100644
index 000000000..b19923228
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs
@@ -0,0 +1,44 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
+ [KeptDelegateCacheField ("0")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.MyEvent += FooOnMyEvent;
+ }
+
+ [Kept]
+ private static void FooOnMyEvent (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+ public event EventHandler MyEvent;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs
new file mode 100644
index 000000000..9683563f9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs
@@ -0,0 +1,36 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs
new file mode 100644
index 000000000..c9ebe388e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+ public int Property { get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs
new file mode 100644
index 000000000..d67bd9177
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs
new file mode 100644
index 000000000..ed284479a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Csc/OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs
@@ -0,0 +1,33 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Csc {
+ /// <summary>
+ /// This explicit csc test exists to ensure that csc adds references in this scenario
+ /// </summary>
+ [SetupCSharpCompilerToUse ("csc")]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithTypeAndReference.dll", new [] { typeof(TypeDefinedInReferenceWithReference) }, new [] { "LibraryWithType.dll", "LibraryWithAttribute.dll" }, compilerToUse: "csc")]
+ [KeptTypeInAssembly ("LibraryWithTypeAndReference.dll", typeof (TypeDefinedInReferenceWithReference))]
+ [RemovedMemberInAssembly ("LibraryWithTypeAndReference.dll", typeof (TypeDefinedInReferenceWithReference), "Unused()")]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ public class OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReferenceWithReference))]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly_Lib.cs b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly_Lib.cs
new file mode 100644
index 000000000..b52782cd8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly_Lib.cs
@@ -0,0 +1,6 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Dependencies {
+ public class AttributeInReferenceAttribute : Attribute {
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AssemblyAttributeKeptInComplexCase_Lib.cs b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AssemblyAttributeKeptInComplexCase_Lib.cs
new file mode 100644
index 000000000..914361f07
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AssemblyAttributeKeptInComplexCase_Lib.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Dependencies {
+ public class AssemblyAttributeKeptInComplexCase_Lib {
+ public class OtherAssemblyAttribute : Attribute {
+ }
+
+ public static void MethodThatWillBeUsed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AttributeDefinedInReference.cs b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AttributeDefinedInReference.cs
new file mode 100644
index 000000000..cc6d8d928
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/AttributeDefinedInReference.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Dependencies {
+ [AttributeUsage (AttributeTargets.All, AllowMultiple = true)]
+ public class AttributeDefinedInReference : Attribute {
+ public Type FieldType;
+
+ public AttributeDefinedInReference ()
+ {
+ }
+
+ public AttributeDefinedInReference (Type t)
+ {
+ }
+
+ public AttributeDefinedInReference (Type[] t)
+ {
+ }
+
+ public Type PropertyType { get; set; }
+ }
+
+ public class AttributeDefinedInReference_OtherType {
+ public static void Method ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReference.cs b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReference.cs
new file mode 100644
index 000000000..76c32933b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReference.cs
@@ -0,0 +1,7 @@
+namespace Mono.Linker.Tests.Cases.Attributes.Dependencies {
+ public class TypeDefinedInReference {
+ public static void Unused ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReference2.cs b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReference2.cs
new file mode 100644
index 000000000..b306dcea5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReference2.cs
@@ -0,0 +1,4 @@
+namespace Mono.Linker.Tests.Cases.Attributes.Dependencies {
+ public class TypeDefinedInReference2 {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReferenceWithReference.cs b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReferenceWithReference.cs
new file mode 100644
index 000000000..2f60f4763
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Dependencies/TypeDefinedInReferenceWithReference.cs
@@ -0,0 +1,8 @@
+namespace Mono.Linker.Tests.Cases.Attributes.Dependencies {
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ public class TypeDefinedInReferenceWithReference {
+ public static void Unused ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/FixedLengthArrayAttributesArePreserved.cs b/test/Mono.Linker.Tests.Cases/Attributes/FixedLengthArrayAttributesArePreserved.cs
new file mode 100644
index 000000000..3c65d0204
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/FixedLengthArrayAttributesArePreserved.cs
@@ -0,0 +1,41 @@
+using System.Runtime.CompilerServices;
+using System.Security;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ /// <summary>
+ /// The purpose of this test is mainly to provide coverage on the `KeptAttributeOnFixedBufferType` attribute
+ /// </summary>
+ [SetupCompileArgument ("/unsafe")]
+ // Can't verify because the test contains unsafe code
+ [SkipPeVerify]
+ public class FixedLengthArrayAttributesArePreserved {
+ public static void Main ()
+ {
+ Helper ();
+ }
+
+ [Kept]
+ static unsafe void Helper ()
+ {
+ var tmp = new WithFixedArrayField ();
+ var v = tmp.Values;
+ AMethodToUseTheReturnValue (v);
+ }
+
+ [Kept]
+ static unsafe void AMethodToUseTheReturnValue (int* ptr)
+ {
+ }
+
+ [Kept]
+ public unsafe struct WithFixedArrayField {
+ [Kept]
+ [KeptFixedBuffer]
+ [KeptAttributeOnFixedBufferType (typeof (UnsafeValueTypeAttribute))]
+ [KeptAttributeAttribute (typeof (FixedBufferAttribute))]
+ public fixed int Values [10];
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs
new file mode 100644
index 000000000..4f06ea861
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType1.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithType2.dll", new [] { typeof(TypeDefinedInReference2) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType1.dll", typeof (TypeDefinedInReference))]
+ [KeptTypeInAssembly ("LibraryWithType2.dll", typeof (TypeDefinedInReference2))]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type[])")]
+ public class OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType {
+ public static void Main()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (new [] { typeof (TypeDefinedInReference), typeof (TypeDefinedInReference2) })]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs
new file mode 100644
index 000000000..18734fff7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs
@@ -0,0 +1,22 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// In the case of attributes on assemblies, we expect both assemblies to be removed because we don't keep assembly level attributes
+ /// when that is the only type marked in the assembly
+ /// </summary>
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [RemovedAssembly ("LibraryWithType.dll")]
+ [RemovedAssembly ("LibraryWithAttribute.dll")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly {
+ public static void Main()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs
new file mode 100644
index 000000000..c3a62bed0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+[assembly: AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof (AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ [KeptTypeInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference_OtherType))]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed {
+ public static void Main ()
+ {
+ // Use something in the attribute assembly so that the special behavior of not preserving a reference if the only thing that is marked
+ // are attributes is not trigged
+ AttributeDefinedInReference_OtherType.Method();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs
new file mode 100644
index 000000000..0df1c12e5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs
@@ -0,0 +1,43 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ [KeptDelegateCacheField ("0")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.MyEvent += FooOnMyEvent;
+ }
+
+ [Kept]
+ private static void FooOnMyEvent (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo
+ {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ [KeptAttributeAttribute (typeof( AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ public event EventHandler MyEvent;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs
new file mode 100644
index 000000000..0d191d7f4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs
@@ -0,0 +1,34 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof (TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof (AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs
new file mode 100644
index 000000000..ec52d0556
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs
@@ -0,0 +1,33 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ public int Property { get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs
new file mode 100644
index 000000000..1708be4a4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof (TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof (AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType {
+ public static void Main()
+ {
+ var foo = new Foo();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReference))]
+ class Foo
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs
new file mode 100644
index 000000000..00394f906
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs
@@ -0,0 +1,23 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: AttributeDefinedInReference (FieldType = typeof (TypeDefinedInReference))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// In the case of attributes on assemblies, we expect both assemblies to be removed because we don't keep assembly level attributes
+ /// when that is the only type marked in the assembly
+ /// </summary>
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [RemovedAssembly ("LibraryWithType.dll")]
+ [RemovedAssembly ("LibraryWithAttribute.dll")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly
+ {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs
new file mode 100644
index 000000000..ad376f852
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs
@@ -0,0 +1,43 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
+ [KeptDelegateCacheField ("0")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.MyEvent += FooOnMyEvent;
+ }
+
+ [Kept]
+ private static void FooOnMyEvent (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (FieldType = typeof (TypeDefinedInReference))]
+ public event EventHandler MyEvent;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs
new file mode 100644
index 000000000..26574eb8a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs
@@ -0,0 +1,36 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod
+ {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (FieldType = typeof(TypeDefinedInReference))]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs
new file mode 100644
index 000000000..87b1853eb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs
@@ -0,0 +1,34 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (FieldType = typeof (TypeDefinedInReference))]
+ public int Property { get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs
new file mode 100644
index 000000000..cd62f5b3d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "FieldType")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (FieldType = typeof (TypeDefinedInReference))]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs
new file mode 100644
index 000000000..54dc92639
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs
@@ -0,0 +1,22 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// In the case of attributes on assemblies, we expect both assemblies to be removed because we don't keep assembly level attributes
+ /// when that is the only type marked in the assembly
+ /// </summary>
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [RemovedAssembly ("LibraryWithType.dll")]
+ [RemovedAssembly ("LibraryWithAttribute.dll")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs
new file mode 100644
index 000000000..3c479943d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs
@@ -0,0 +1,43 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
+ [KeptDelegateCacheField ("0")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.MyEvent += FooOnMyEvent;
+ }
+
+ [Kept]
+ private static void FooOnMyEvent (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+ public event EventHandler MyEvent;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs
new file mode 100644
index 000000000..41d1c803e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs
new file mode 100644
index 000000000..66d1a04af
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs
@@ -0,0 +1,34 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ foo.Property = 1;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ [KeptBackingField]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+ public int Property { get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs
new file mode 100644
index 000000000..668f8a9ab
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), "set_PropertyType(System.Type)")]
+ public class OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (PropertyType = typeof (TypeDefinedInReference))]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs
new file mode 100644
index 000000000..22a34cffb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/Mcs/OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs
@@ -0,0 +1,32 @@
+using Mono.Linker.Tests.Cases.Attributes.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.Mcs {
+ /// <summary>
+ /// This explicit mcs test exists because mcs did not add a reference prior to https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5
+ /// </summary>
+ [IgnoreTestCase ("Can be enabled once the mcs contains https://github.com/mono/mono/commit/f71b208ca7b41a2a97ca70b955df0c4c411ce8e5")]
+ [SetupCSharpCompilerToUse ("mcs")]
+ [SetupCompileBefore ("LibraryWithAttribute.dll", new [] { typeof(AttributeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithType.dll", new [] { typeof(TypeDefinedInReference) })]
+ [SetupCompileBefore ("LibraryWithTypeAndReference.dll", new [] { typeof(TypeDefinedInReferenceWithReference) }, new [] { "LibraryWithType.dll", "LibraryWithAttribute.dll" }, compilerToUse: "mcs")]
+ [KeptTypeInAssembly ("LibraryWithTypeAndReference.dll", typeof (TypeDefinedInReferenceWithReference))]
+ [RemovedMemberInAssembly ("LibraryWithTypeAndReference.dll", typeof (TypeDefinedInReferenceWithReference), "Unused()")]
+ [KeptTypeInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference))]
+ [RemovedMemberInAssembly ("LibraryWithType.dll", typeof (TypeDefinedInReference), "Unused()")]
+ [KeptMemberInAssembly ("LibraryWithAttribute.dll", typeof (AttributeDefinedInReference), ".ctor(System.Type)")]
+ public class OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType {
+ public static void Main ()
+ {
+ var foo = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (AttributeDefinedInReference))]
+ [AttributeDefinedInReference (typeof (TypeDefinedInReferenceWithReference))]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/CoreLibrarySecurityAttributeTypesAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/CoreLibrarySecurityAttributeTypesAreRemoved.cs
new file mode 100644
index 000000000..153fe9469
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/CoreLibrarySecurityAttributeTypesAreRemoved.cs
@@ -0,0 +1,43 @@
+using System.Diagnostics;
+using System.Security;
+using System.Security.Permissions;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.NoSecurity {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerArgument ("--strip-security", "true")]
+ [Reference ("System.dll")]
+ // Attributes from System.Security.Permissions
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SecurityPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (PermissionSetAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (ReflectionPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (RegistryPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (StrongNameIdentityPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (CodeAccessSecurityAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (EnvironmentPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (FileIOPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (HostProtectionAttribute))]
+
+ // "Special" attributes from System.Security namespace that we seem to need to remove in order to set HasSecurity = false and not have
+ // pe verify complain
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SecurityCriticalAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SecuritySafeCriticalAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SuppressUnmanagedCodeSecurityAttribute))]
+
+ // Fails with `Runtime critical type System.Reflection.CustomAttributeData not found` which is a known short coming
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ [SkipPeVerify ("System.dll")]
+
+ // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
+ // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
+ // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
+ [SkipPeVerify ("System.Core.dll")]
+ public class CoreLibrarySecurityAttributeTypesAreRemoved {
+ public static void Main ()
+ {
+ // Use something that has security attributes to make this test more meaningful
+ var process = new Process ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/SecurityAttributesOnUsedMethodAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/SecurityAttributesOnUsedMethodAreRemoved.cs
new file mode 100644
index 000000000..eba5ba81f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/SecurityAttributesOnUsedMethodAreRemoved.cs
@@ -0,0 +1,24 @@
+using System.Security.Permissions;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.NoSecurity {
+ [SetupLinkerArgument ("--strip-security", "true")]
+ public class SecurityAttributesOnUsedMethodAreRemoved {
+ static void Main ()
+ {
+ new Foo ().Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [SecurityPermission (SecurityAction.LinkDemand)]
+ [Kept]
+ [RemovedPseudoAttribute (16384)]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/SecurityAttributesOnUsedTypeAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/SecurityAttributesOnUsedTypeAreRemoved.cs
new file mode 100644
index 000000000..a5b251400
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/NoSecurity/SecurityAttributesOnUsedTypeAreRemoved.cs
@@ -0,0 +1,20 @@
+using System.Security.Permissions;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.NoSecurity {
+ [SetupLinkerArgument ("--strip-security", "true")]
+ public class SecurityAttributesOnUsedTypeAreRemoved {
+ static void Main ()
+ {
+ new Foo ();
+ }
+
+ [SecurityPermission (SecurityAction.LinkDemand)]
+ [Kept]
+ [KeptMember (".ctor()")]
+ [RemovedPseudoAttribute (262144u)]
+ class Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/AttributeDefinedAndUsedInOtherAssemblyIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/AttributeDefinedAndUsedInOtherAssemblyIsKept.cs
new file mode 100644
index 000000000..826ad0011
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/AttributeDefinedAndUsedInOtherAssemblyIsKept.cs
@@ -0,0 +1,24 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.cs" })]
+ [KeptMemberInAssembly ("library.dll", typeof (AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.FooAttribute), ".ctor()")]
+ class AttributeDefinedAndUsedInOtherAssemblyIsKept {
+ static void Main ()
+ {
+ Method ();
+ }
+
+ [AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.Foo]
+ [Kept]
+ [KeptAttributeAttribute (typeof (AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.FooAttribute))]
+ static void Method ()
+ {
+ AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.UseTheAttributeType ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/AttributeUsedByAttributeIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/AttributeUsedByAttributeIsKept.cs
new file mode 100644
index 000000000..3c7c0d292
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/AttributeUsedByAttributeIsKept.cs
@@ -0,0 +1,102 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class AttributeUsedByAttributeIsKept {
+ static void Main ()
+ {
+ var jar = new Jar ();
+ jar.SomeMethod ();
+ }
+
+ [Foo]
+ [Bar]
+ [Kar]
+ [NotUsed]
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof(FooAttribute))]
+ [KeptAttributeAttribute (typeof(BarAttribute))]
+ [KeptAttributeAttribute (typeof(KarAttribute))]
+ class Jar {
+ [Kept]
+ public void SomeMethod ()
+ {
+ var attr = typeof (Jar).GetCustomAttributes (typeof (FooAttribute), false) [0];
+ var asFooAttr = (FooAttribute) attr;
+ asFooAttr.MethodWeWillCall ();
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof(Attribute))]
+ class FooAttribute : Attribute {
+ [Kept]
+ public FooAttribute ()
+ {
+ // This ctor should be marked lazy. So let's use another attribute type here which should then trigger that attribute
+ // to be marked
+ var str = typeof (BarAttribute).ToString ();
+ MethodsUsedFromLateMarking.Method1 ();
+ }
+
+ [Foo]
+ [Bar]
+ [Kar]
+ [NotUsed]
+ [Kept]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ [KeptAttributeAttribute (typeof (BarAttribute))]
+ [KeptAttributeAttribute (typeof (KarAttribute))]
+ public void MethodWeWillCall ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof(Attribute))]
+ class BarAttribute : Attribute {
+ [Kept]
+ public BarAttribute ()
+ {
+ // Let's do this one more time to make sure we catch everything
+ var str = typeof (KarAttribute).ToString ();
+ MethodsUsedFromLateMarking.Method2 ();
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Attribute))]
+ class KarAttribute : Attribute {
+ [Kept]
+ public KarAttribute ()
+ {
+ MethodsUsedFromLateMarking.Method3 ();
+ }
+ }
+
+ class NotUsedAttribute : Attribute {
+ }
+
+ [Kept]
+ static class MethodsUsedFromLateMarking {
+ [Kept]
+ public static void Method1 ()
+ {
+ }
+
+ [Kept]
+ public static void Method2 ()
+ {
+ }
+
+ [Kept]
+ public static void Method3 ()
+ {
+ }
+ }
+
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs
new file mode 100644
index 000000000..6599677e4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Timers;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [Reference ("System.dll")]
+ // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
+ // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
+ // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
+ [SkipPeVerify ("System.Core.dll")]
+ // Fails with `Runtime critical type System.Reflection.CustomAttributeData not found`
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ class CanLinkCoreLibrariesWithOnlyKeepUsedAttributes {
+ static void Main ()
+ {
+ // Use something from System so that the entire reference isn't linked away
+ var system = new Timer ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ComAttributesArePreserved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ComAttributesArePreserved.cs
new file mode 100644
index 000000000..8c34640d1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ComAttributesArePreserved.cs
@@ -0,0 +1,31 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ /// <summary>
+ /// COM related attributes are required at runtime
+ /// </summary>
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ public class ComAttributesArePreserved {
+ public static void Main ()
+ {
+ var tmp = ReturnValueUsedToMarkType ();
+ }
+
+ [Kept]
+ static A ReturnValueUsedToMarkType ()
+ {
+ return null;
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [KeptAttributeAttribute (typeof (InterfaceTypeAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
+ interface A {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ComAttributesAreRemovedWhenFeatureExcluded.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ComAttributesAreRemovedWhenFeatureExcluded.cs
new file mode 100644
index 000000000..ca83503d4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ComAttributesAreRemovedWhenFeatureExcluded.cs
@@ -0,0 +1,28 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [SetupLinkerArgument ("--exclude-feature", "com")]
+ public class ComAttributesAreRemovedWhenFeatureExcluded {
+ public static void Main ()
+ {
+ var tmp = ReturnValueUsedToMarkType ();
+ }
+
+ [Kept]
+ static A ReturnValueUsedToMarkType ()
+ {
+ return null;
+ }
+
+ [Kept]
+ [RemovedPseudoAttribute (0x00001000u)]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
+ interface A {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ContextStaticIsPreservedOnField.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ContextStaticIsPreservedOnField.cs
new file mode 100644
index 000000000..39fecc123
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ContextStaticIsPreservedOnField.cs
@@ -0,0 +1,21 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ /// <summary>
+ /// [ContextStatic] is required by the mono runtime
+ /// </summary>
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ public class ContextStaticIsPreservedOnField {
+ [ContextStatic]
+ [Kept]
+ [KeptAttributeAttribute (typeof (ContextStaticAttribute))]
+ public static int UsedField;
+
+ public static void Main ()
+ {
+ UsedField = 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs
new file mode 100644
index 000000000..476f279c1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUnusedAssemblyAttributesAreRemoved.cs
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Timers;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [Reference ("System.dll")]
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [RemovedAttributeInAssembly ("mscorlib.dll", typeof (AssemblyDescriptionAttribute))]
+ [RemovedAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))]
+ [SkipPeVerify]
+ public class CoreLibraryUnusedAssemblyAttributesAreRemoved {
+ public static void Main ()
+ {
+ // Use something from System so that the entire reference isn't linked away
+ var system = new Timer ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs
new file mode 100644
index 000000000..46cb2f1f3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/CoreLibraryUsedAssemblyAttributesAreKept.cs
@@ -0,0 +1,23 @@
+using System.Reflection;
+using System.Timers;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [Reference ("System.dll")]
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [KeptAttributeInAssembly ("mscorlib.dll", typeof (AssemblyDescriptionAttribute))]
+ [KeptAttributeInAssembly ("System.dll", typeof (AssemblyDescriptionAttribute))]
+ [SkipPeVerify]
+ public class CoreLibraryUsedAssemblyAttributesAreKept {
+ public static void Main ()
+ {
+ // Use something from System so that the entire reference isn't linked away
+ var system = new Timer ();
+
+ // use one of the attribute types so that it is marked
+ var tmp = typeof (AssemblyDescriptionAttribute).ToString ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/AssemblyWithUnusedAttributeOnReturnParameterDefinition.il b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/AssemblyWithUnusedAttributeOnReturnParameterDefinition.il
new file mode 100644
index 000000000..90b51a91a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/AssemblyWithUnusedAttributeOnReturnParameterDefinition.il
@@ -0,0 +1,54 @@
+.assembly extern mscorlib
+{
+}
+.assembly 'library'
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module library.dll
+
+
+.namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies
+{
+ .class public auto ansi beforefieldinit AssemblyWithUnusedAttributeOnReturnParameterDefinition
+ extends [mscorlib]System.Object
+ {
+
+ .method public hidebysig specialname rtspecialname
+ instance default void '.ctor' () cil managed
+ {
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void object::'.ctor'()
+ IL_0006: ret
+ }
+
+ .method public hidebysig
+ instance default int32 Method (int32 arg) cil managed
+ {
+ .param [0]
+ .custom instance void class Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies.AssemblyWithUnusedAttributeOnReturnParameterDefinition/FooAttribute::'.ctor'() = (01 00 00 00 ) // ....
+
+ .maxstack 8
+ IL_0000: ldarg.1
+ IL_0001: ret
+ }
+
+ .class nested private auto ansi beforefieldinit FooAttribute
+ extends [mscorlib]System.Attribute
+ {
+
+ .method public hidebysig specialname rtspecialname
+ instance default void '.ctor' () cil managed
+ {
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void class [mscorlib]System.Attribute::'.ctor'()
+ IL_0006: ret
+ }
+
+ }
+ }
+}
+
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.cs
new file mode 100644
index 000000000..c94d85ba0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies {
+ public class AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib {
+ public static void UseTheAttributeType ()
+ {
+ var str = typeof (FooAttribute).ToString ();
+ }
+
+ public class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Forwarder.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Forwarder.cs
new file mode 100644
index 000000000..9bea6c499
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Forwarder.cs
@@ -0,0 +1,6 @@
+using System;
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies;
+
+[assembly: TypeForwardedTo (typeof (UnusedAttributeWithTypeForwarderIsRemoved_LibAttribute))]
+[assembly: TypeForwardedTo (typeof (UnusedAttributeWithTypeForwarderIsRemoved_OtherUsedClass))]
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Lib.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Lib.cs
new file mode 100644
index 000000000..b22c07be9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Lib.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies {
+ public class UnusedAttributeWithTypeForwarderIsRemoved_LibAttribute : Attribute {
+ public UnusedAttributeWithTypeForwarderIsRemoved_LibAttribute (string arg)
+ {
+ }
+ }
+
+ public class UnusedAttributeWithTypeForwarderIsRemoved_OtherUsedClass {
+ public static void UsedMethod ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/FixedLengthArrayAttributesArePreserved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/FixedLengthArrayAttributesArePreserved.cs
new file mode 100644
index 000000000..3e33c8584
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/FixedLengthArrayAttributesArePreserved.cs
@@ -0,0 +1,38 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [SetupCompileArgument ("/unsafe")]
+
+ // Can't verify because the test contains unsafe code
+ [SkipPeVerify]
+ public class FixedLengthArrayAttributesArePreserved {
+ public static void Main ()
+ {
+ Helper ();
+ }
+
+ [Kept]
+ static unsafe void Helper ()
+ {
+ var tmp = new WithFixedArrayField ();
+ var v = tmp.Values;
+ AMethodToUseTheReturnValue (v);
+ }
+
+ [Kept]
+ static unsafe void AMethodToUseTheReturnValue (int* ptr)
+ {
+ }
+
+ [Kept]
+ public unsafe struct WithFixedArrayField {
+ [Kept]
+ [KeptFixedBuffer]
+ [KeptAttributeAttribute (typeof (FixedBufferAttribute))]
+ public fixed int Values [10];
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ThreadStaticIsPreservedOnField.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ThreadStaticIsPreservedOnField.cs
new file mode 100644
index 000000000..35ed32fc1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/ThreadStaticIsPreservedOnField.cs
@@ -0,0 +1,21 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ /// <summary>
+ /// [ThreadStatic] is required by the mono runtime
+ /// </summary>
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ public class ThreadStaticIsPreservedOnField {
+ [ThreadStatic]
+ [Kept]
+ [KeptAttributeAttribute (typeof (ThreadStaticAttribute))]
+ public static int UsedField;
+
+ public static void Main ()
+ {
+ UsedField = 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeOnReturnTypeIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeOnReturnTypeIsRemoved.cs
new file mode 100644
index 000000000..62d1b368d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeOnReturnTypeIsRemoved.cs
@@ -0,0 +1,17 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [Define ("IL_ASSEMBLY_AVAILABLE")]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/AssemblyWithUnusedAttributeOnReturnParameterDefinition.il" })]
+ [RemovedTypeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies.AssemblyWithUnusedAttributeOnReturnParameterDefinition/FooAttribute")]
+ public class UnusedAttributeOnReturnTypeIsRemoved {
+ static void Main ()
+ {
+#if IL_ASSEMBLY_AVAILABLE
+ var tmp = new Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies.AssemblyWithUnusedAttributeOnReturnParameterDefinition ().Method (1);
+#endif
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributePreservedViaLinkXmlIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributePreservedViaLinkXmlIsKept.cs
new file mode 100644
index 000000000..c7273e993
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributePreservedViaLinkXmlIsKept.cs
@@ -0,0 +1,33 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UnusedAttributePreservedViaLinkXmlIsKept {
+ static void Main ()
+ {
+ var tmp = new Bar ();
+ tmp.Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ [Foo]
+ class Bar {
+ [Kept]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ [Foo]
+ public void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributePreservedViaLinkXmlIsKept.xml b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributePreservedViaLinkXmlIsKept.xml
new file mode 100644
index 000000000..02a75666f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributePreservedViaLinkXmlIsKept.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.UnusedAttributePreservedViaLinkXmlIsKept/FooAttribute" preserve="all">
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnAssemblyIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnAssemblyIsRemoved.cs
new file mode 100644
index 000000000..bbe066f6f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnAssemblyIsRemoved.cs
@@ -0,0 +1,17 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: UnusedAttributeTypeOnAssemblyIsRemoved.Foo]
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UnusedAttributeTypeOnAssemblyIsRemoved {
+ static void Main ()
+ {
+ }
+
+ public class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs
new file mode 100644
index 000000000..9f0a5271c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnEventIsRemoved.cs
@@ -0,0 +1,33 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [KeptDelegateCacheField ("0")]
+ class UnusedAttributeTypeOnEventIsRemoved {
+ static void Main ()
+ {
+ var tmp = new Bar ();
+ tmp.Something += Tmp_Something;
+ }
+
+ [Kept]
+ private static void Tmp_Something (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ [Foo]
+ [Kept]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event EventHandler<EventArgs> Something { [Foo] add { } [Foo] remove { } }
+ }
+
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnMethodIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnMethodIsRemoved.cs
new file mode 100644
index 000000000..2804e2ff4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnMethodIsRemoved.cs
@@ -0,0 +1,30 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
+ // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
+ // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
+ [SkipPeVerify ("System.Core.dll")]
+ class UnusedAttributeTypeOnMethodIsRemoved {
+ static void Main ()
+ {
+ new Bar ().Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ [Foo]
+ [Kept]
+ public void Method ()
+ {
+ }
+ }
+
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnModuleIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnModuleIsRemoved.cs
new file mode 100644
index 000000000..90619679c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnModuleIsRemoved.cs
@@ -0,0 +1,17 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[module: UnusedAttributeTypeOnModuleIsRemoved.Foo]
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UnusedAttributeTypeOnModuleIsRemoved {
+ static void Main ()
+ {
+ }
+
+ public class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnParameterIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnParameterIsRemoved.cs
new file mode 100644
index 000000000..c74e4f6c0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnParameterIsRemoved.cs
@@ -0,0 +1,25 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UnusedAttributeTypeOnParameterIsRemoved {
+ static void Main ()
+ {
+ new Bar ().Method ("Hello");
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ [Kept]
+ public void Method ([Foo] string arg)
+ {
+ }
+ }
+
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnPropertyIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnPropertyIsRemoved.cs
new file mode 100644
index 000000000..7144700ff
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnPropertyIsRemoved.cs
@@ -0,0 +1,27 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UnusedAttributeTypeOnPropertyIsRemoved {
+ static void Main ()
+ {
+ var bar = new Bar ();
+ bar.Value = "Hello";
+ var tmp = bar.Value;
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ [Foo]
+ [Kept]
+ [KeptBackingField]
+ public string Value { [Foo] [Kept] get; [Foo] [Kept] set; }
+ }
+
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnTypeIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnTypeIsRemoved.cs
new file mode 100644
index 000000000..03aba0d14
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeTypeOnTypeIsRemoved.cs
@@ -0,0 +1,22 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UnusedAttributeTypeOnTypeIsRemoved {
+ static void Main ()
+ {
+ new Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [Foo]
+ class Bar {
+ }
+
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeWithTypeForwarderIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeWithTypeForwarderIsRemoved.cs
new file mode 100644
index 000000000..49167f6a7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UnusedAttributeWithTypeForwarderIsRemoved.cs
@@ -0,0 +1,28 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [KeepTypeForwarderOnlyAssemblies ("true")]
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [SetupCompileBefore ("library.dll", new[] { "Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Lib.cs" })]
+ [SetupCompileAfter ("implementation.dll", new[] { "Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Lib.cs" })]
+ [SetupCompileAfter ("library.dll", new[] { "Dependencies/UnusedAttributeWithTypeForwarderIsRemoved_Forwarder.cs" }, new[] { "implementation.dll" })]
+
+ [RemovedTypeInAssembly ("library.dll", typeof(UnusedAttributeWithTypeForwarderIsRemoved_LibAttribute))]
+ [RemovedTypeInAssembly ("implementation.dll", typeof (UnusedAttributeWithTypeForwarderIsRemoved_LibAttribute))]
+ class UnusedAttributeWithTypeForwarderIsRemoved {
+ static void Main ()
+ {
+ Method (null);
+ }
+
+ [Kept]
+
+ static void Method ([UnusedAttributeWithTypeForwarderIsRemoved_Lib ("")] string arg)
+ {
+ UnusedAttributeWithTypeForwarderIsRemoved_OtherUsedClass.UsedMethod ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnAssemblyIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnAssemblyIsKept.cs
new file mode 100644
index 000000000..3f84fddbb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnAssemblyIsKept.cs
@@ -0,0 +1,23 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+[assembly: UsedAttributeTypeOnAssemblyIsKept.Foo]
+[assembly: KeptAttributeAttribute (typeof (UsedAttributeTypeOnAssemblyIsKept.FooAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument("--used-attrs-only", "true")]
+ class UsedAttributeTypeOnAssemblyIsKept {
+ static void Main ()
+ {
+ var str = typeof (FooAttribute).ToString ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Attribute))]
+ public class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs
new file mode 100644
index 000000000..72fb256dc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnEventIsKept.cs
@@ -0,0 +1,38 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [KeptDelegateCacheField ("0")]
+ class UsedAttributeTypeOnEventIsKept {
+ static void Main ()
+ {
+ var tmp = new Bar ();
+ tmp.Something += Tmp_Something;
+ var str = typeof (FooAttribute).ToString ();
+ }
+
+ [Kept]
+ private static void Tmp_Something (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ [Foo]
+ [Kept]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event EventHandler<EventArgs> Something { [Foo] [KeptAttributeAttribute (typeof (FooAttribute))] add { } [Foo] [KeptAttributeAttribute (typeof (FooAttribute))] remove { } }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof(Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnMethodIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnMethodIsKept.cs
new file mode 100644
index 000000000..fc8516f87
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnMethodIsKept.cs
@@ -0,0 +1,32 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UsedAttributeTypeOnMethodIsKept {
+ static void Main ()
+ {
+ new Bar ().Method ();
+ var tmp = new Bar ();
+ var str = typeof (FooAttribute).ToString ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ [Foo]
+ [Kept]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ public void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof(Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnModuleIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnModuleIsKept.cs
new file mode 100644
index 000000000..72e9906df
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnModuleIsKept.cs
@@ -0,0 +1,23 @@
+using System;
+using Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[module: UsedAttributeTypeOnModuleIsKept.Foo]
+[module: KeptAttributeAttribute (typeof (UsedAttributeTypeOnModuleIsKept.FooAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UsedAttributeTypeOnModuleIsKept {
+ static void Main ()
+ {
+ var str = typeof (FooAttribute).ToString ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Attribute))]
+ public class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnParameterIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnParameterIsKept.cs
new file mode 100644
index 000000000..4fb4b134b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnParameterIsKept.cs
@@ -0,0 +1,29 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UsedAttributeTypeOnParameterIsKept {
+ static void Main ()
+ {
+ new Bar ().Method ("Hello");
+ var str = typeof (FooAttribute).ToString ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ [Kept]
+ public void Method ([Foo] [KeptAttributeAttribute (typeof (FooAttribute))] string arg)
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof(Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnPropertyIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnPropertyIsKept.cs
new file mode 100644
index 000000000..8932d7252
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnPropertyIsKept.cs
@@ -0,0 +1,32 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UsedAttributeTypeOnPropertyIsKept {
+ static void Main ()
+ {
+ var bar = new Bar ();
+ bar.Value = "Hello";
+ var tmp = bar.Value;
+ var str = typeof (FooAttribute).ToString ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ [Foo]
+ [Kept]
+ [KeptBackingField]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ public string Value { [Foo] [Kept] [KeptAttributeAttribute (typeof (FooAttribute))] get; [Foo] [Kept] [KeptAttributeAttribute (typeof (FooAttribute))]set; }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof(Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnTypeIsKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnTypeIsKept.cs
new file mode 100644
index 000000000..04dba4d26
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/OnlyKeepUsed/UsedAttributeTypeOnTypeIsKept.cs
@@ -0,0 +1,28 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes.OnlyKeepUsed {
+
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ class UsedAttributeTypeOnTypeIsKept {
+ static void Main ()
+ {
+ var tmp = new Bar ();
+ var str = typeof (FooAttribute).ToString ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (FooAttribute))]
+ [Foo]
+ class Bar {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Attribute))]
+ class FooAttribute : Attribute {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/SecurityAttributesOnUsedMethodAreKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/SecurityAttributesOnUsedMethodAreKept.cs
new file mode 100644
index 000000000..6ffa3845a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/SecurityAttributesOnUsedMethodAreKept.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Security.Permissions;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [SetupLinkerArgument ("--strip-security", "false")]
+ class SecurityAttributesOnUsedMethodAreKept {
+ static void Main ()
+ {
+ new Foo ().Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [SecurityPermission (SecurityAction.LinkDemand)]
+ [Kept]
+ [KeptSecurity (typeof (SecurityPermissionAttribute))]
+ public void Method ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Attributes/SecurityAttributesOnUsedTypeAreKept.cs b/test/Mono.Linker.Tests.Cases/Attributes/SecurityAttributesOnUsedTypeAreKept.cs
new file mode 100644
index 000000000..080fe2096
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Attributes/SecurityAttributesOnUsedTypeAreKept.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Security.Permissions;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Attributes {
+ [SetupLinkerArgument("--strip-security", "false")]
+ class SecurityAttributesOnUsedTypeAreKept {
+ static void Main ()
+ {
+ new Foo ();
+ }
+
+ [SecurityPermission (SecurityAction.LinkDemand)]
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptSecurity (typeof (SecurityPermissionAttribute))]
+ class Foo {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/BaseRemovedEventSource.cs b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/BaseRemovedEventSource.cs
new file mode 100644
index 000000000..d63d45a7c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/BaseRemovedEventSource.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Diagnostics.Tracing;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.BCLFeatures.ETW {
+ [SetupLinkerArgument ("--exclude-feature", "etw")]
+ public class BaseRemovedEventSource {
+ public static void Main ()
+ {
+ var b = CustomCtorEventSource.Log.IsEnabled ();
+ if (b)
+ CustomCtorEventSource.Log.SomeMethod ();
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (EventSource))]
+ [KeptMember (".ctor()")]
+ [KeptMember (".cctor()")]
+ [EventSource (Name = "MyCompany")]
+ class CustomCtorEventSource : EventSource {
+ public class Keywords {
+ public const EventKeywords Page = (EventKeywords)1;
+
+ public int Unused;
+ }
+
+ [Kept]
+ public static CustomCtorEventSource Log = new MyEventSourceBasedOnCustomCtorEventSource (1);
+
+ [Kept]
+ [ExpectedInstructionSequence (new []
+ {
+ "ldarg.0",
+ "call",
+ "ret",
+ })]
+ public CustomCtorEventSource (int value)
+ {
+ Removed ();
+ }
+
+ [Kept]
+ [ExpectedInstructionSequence (new []
+ {
+ "ldstr",
+ "newobj",
+ "throw",
+ })]
+ protected override void OnEventCommand (EventCommandEventArgs command)
+ {
+ }
+
+ [Kept]
+ [ExpectedInstructionSequence (new []
+ {
+ "ldstr",
+ "newobj",
+ "throw",
+ })]
+ [Event (8)]
+ public void SomeMethod ()
+ {
+ Removed ();
+ }
+
+ public void Removed ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (CustomCtorEventSource))]
+ class MyEventSourceBasedOnCustomCtorEventSource : CustomCtorEventSource {
+ [Kept]
+ public MyEventSourceBasedOnCustomCtorEventSource (int value) : base (value)
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomEventSource.cs b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomEventSource.cs
new file mode 100644
index 000000000..8286f22c5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/CustomEventSource.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Diagnostics.Tracing;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.BCLFeatures.ETW {
+ public class CustomEventSource {
+ public static void Main ()
+ {
+ var b = MyCompanyEventSource.Log.IsEnabled ();
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (EventSource))]
+ [KeptAttributeAttribute (typeof (EventSourceAttribute))]
+ [KeptMember (".ctor()")]
+ [KeptMember (".cctor()")]
+
+ [EventSource (Name = "MyCompany")]
+ class MyCompanyEventSource : EventSource
+ {
+ [Kept]
+ public class Keywords
+ {
+ [Kept]
+ public const EventKeywords Page = (EventKeywords)1;
+
+ public int Unused;
+ }
+
+ [Kept]
+ public class Tasks
+ {
+ [Kept]
+ public const EventTask Page = (EventTask)1;
+
+ public int Unused;
+ }
+
+ class NotMatching
+ {
+ }
+
+ [Kept]
+ public static MyCompanyEventSource Log = new MyCompanyEventSource ();
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/Excluded.cs b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/Excluded.cs
new file mode 100644
index 000000000..575a7dec0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/Excluded.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Diagnostics.Tracing;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.BCLFeatures.ETW {
+ [SetupLinkerArgument ("--exclude-feature", "etw")]
+ // Used to avoid different compilers generating different IL which can mess up the instruction asserts
+ [SetupCompileArgument ("/optimize+")]
+ public class Excluded
+ {
+ public static void Main ()
+ {
+ var b = RemovedEventSource.Log.IsEnabled ();
+ if (b)
+ RemovedEventSource.Log.SomeMethod ();
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (EventSource))]
+ [KeptMember (".ctor()")]
+ [KeptMember (".cctor()")]
+ [EventSource (Name = "MyCompany")]
+ class RemovedEventSource : EventSource {
+ public class Keywords {
+ public const EventKeywords Page = (EventKeywords)1;
+
+ public int Unused;
+ }
+
+ [Kept]
+ public static RemovedEventSource Log = new RemovedEventSource ();
+
+ [Kept]
+ [ExpectedInstructionSequence (new []
+ {
+ "ldstr",
+ "newobj",
+ "throw",
+ })]
+ protected override void OnEventCommand (EventCommandEventArgs command)
+ {
+ }
+
+ [Kept]
+ [ExpectedInstructionSequence (new []
+ {
+ "ldstr",
+ "newobj",
+ "throw",
+ })]
+ [Event (8)]
+ public void SomeMethod ()
+ {
+ Removed ();
+ }
+
+ public void Removed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/LocalsOfModifiedMethodAreRemoved.cs b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/LocalsOfModifiedMethodAreRemoved.cs
new file mode 100644
index 000000000..1a5b1cb80
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/LocalsOfModifiedMethodAreRemoved.cs
@@ -0,0 +1,65 @@
+using System.Diagnostics.Tracing;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.BCLFeatures.ETW {
+ [SetupLinkerArgument ("--exclude-feature", "etw")]
+ // Used to avoid different compilers generating different IL which can mess up the instruction asserts
+ [SetupCompileArgument ("/optimize+")]
+ public class LocalsOfModifiedMethodAreRemoved {
+ public static void Main ()
+ {
+ var b = LocalsAreCleared_RemovedEventSource.Log.IsEnabled ();
+ if (b)
+ LocalsAreCleared_RemovedEventSource.Log.SomeMethod ();
+ }
+
+ public class ClassForLocal {
+ }
+
+ public static void CallsToForceALocal (int arg1, int arg2, int arg3)
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (EventSource))]
+ [KeptMember (".ctor()")]
+ [KeptMember (".cctor()")]
+ [EventSource (Name = "MyCompany")]
+ class LocalsAreCleared_RemovedEventSource : EventSource {
+ public class Keywords {
+ public const EventKeywords Page = (EventKeywords)1;
+
+ public int Unused;
+ }
+
+ [Kept]
+ public static LocalsAreCleared_RemovedEventSource Log = new LocalsAreCleared_RemovedEventSource ();
+
+ [Kept]
+ [ExpectBodyModified]
+ [ExpectedLocalsSequence (new string[0])]
+ protected override void OnEventCommand (EventCommandEventArgs command)
+ {
+ // Do some extra stuff to be extra certain the compiler introduced a local instead of using `dup`
+ var tmp = new LocalsOfModifiedMethodAreRemoved.ClassForLocal ();
+ LocalsOfModifiedMethodAreRemoved.CallsToForceALocal (1, 3, 4);
+ LocalsOfModifiedMethodAreRemoved.CallsToForceALocal (1, 4, 4);
+ var hashcode = tmp.GetHashCode ();
+ LocalsOfModifiedMethodAreRemoved.CallsToForceALocal(1, hashcode, 3);
+ }
+
+ [Kept]
+ [Event (8)]
+ [ExpectBodyModified]
+ public void SomeMethod ()
+ {
+ Removed ();
+ }
+
+ public void Removed ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/NonEventWithLog.cs b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/NonEventWithLog.cs
new file mode 100644
index 000000000..5b0b82f18
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/NonEventWithLog.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Diagnostics.Tracing;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.BCLFeatures.ETW {
+ [SetupLinkerArgument ("--exclude-feature", "etw")]
+ // Used to avoid different compilers generating different IL which can mess up the instruction asserts
+ [SetupCompileArgument ("/optimize+")]
+ public class NonEventWithLog {
+ public static void Main ()
+ {
+ var n = new NonEventWithLogSource ();
+ n.Test1 ();
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (EventSource))]
+ [KeptMember (".ctor()")]
+
+ [EventSource (Name = "MyCompany")]
+ class NonEventWithLogSource : EventSource {
+
+ [NonEvent]
+ [Kept]
+ internal void Test1 ()
+ {
+ if (IsEnabled ())
+ Test2 ();
+ }
+
+ [Kept]
+ [ExpectedInstructionSequence (new []
+ {
+ "ldstr",
+ "newobj",
+ "throw",
+ })]
+ private void Test2 ()
+ {
+ Console.WriteLine ();
+ }
+
+ [NonEvent]
+ private void Test3 ()
+ {
+ Console.WriteLine ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/StubbedMethodWithExceptionHandlers.cs b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/StubbedMethodWithExceptionHandlers.cs
new file mode 100644
index 000000000..e3f76779f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/BCLFeatures/ETW/StubbedMethodWithExceptionHandlers.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Diagnostics.Tracing;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.BCLFeatures.ETW {
+ [SetupLinkerArgument ("--exclude-feature", "etw")]
+ // Used to avoid different compilers generating different IL which can mess up the instruction asserts
+ [SetupCompileArgument ("/optimize+")]
+ public class StubbedMethodWithExceptionHandlers {
+ public static void Main ()
+ {
+ var b = StubbedMethodWithExceptionHandlers_RemovedEventSource.Log.IsEnabled ();
+ if (b)
+ StubbedMethodWithExceptionHandlers_RemovedEventSource.Log.SomeMethod ();
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (EventSource))]
+ [KeptMember (".ctor()")]
+ [KeptMember (".cctor()")]
+ [EventSource (Name = "MyCompany")]
+ class StubbedMethodWithExceptionHandlers_RemovedEventSource : EventSource {
+ public class Keywords {
+ public const EventKeywords Page = (EventKeywords)1;
+
+ public int Unused;
+ }
+
+ [Kept]
+ public static StubbedMethodWithExceptionHandlers_RemovedEventSource Log = new StubbedMethodWithExceptionHandlers_RemovedEventSource ();
+
+ [Kept]
+ [ExpectedInstructionSequence (new []
+ {
+ "ldstr",
+ "newobj",
+ "throw",
+ })]
+ [ExpectedExceptionHandlerSequence (new string[0])]
+ protected override void OnEventCommand (EventCommandEventArgs command)
+ {
+ try {
+ Removed ();
+ } catch {
+ try {
+ Removed ();
+ } catch {
+ Removed ();
+ throw;
+ }
+ throw;
+ }
+ }
+
+ [Kept]
+ [ExpectedInstructionSequence (new []
+ {
+ "ldstr",
+ "newobj",
+ "throw",
+ })]
+ [Event (8)]
+ public void SomeMethod ()
+ {
+ Removed ();
+ }
+
+ public void Removed ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/ComplexNestedClassesHasUnusedRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/ComplexNestedClassesHasUnusedRemoved.cs
new file mode 100644
index 000000000..fbdbee204
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/ComplexNestedClassesHasUnusedRemoved.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class ComplexNestedClassesHasUnusedRemoved {
+ public static void Main ()
+ {
+ new A.AB.ABD ();
+ }
+
+ [Kept]
+ public class A {
+ [Kept]
+ public class AB {
+ public class ABC {
+ }
+
+ [Kept]
+ [KeptMember(".ctor()")]
+ public class ABD {
+ public class ABDE {
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/InitializerForArrayIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/InitializerForArrayIsKept.cs
new file mode 100644
index 000000000..7d461c741
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/InitializerForArrayIsKept.cs
@@ -0,0 +1,40 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ public class InitializerForArrayIsKept {
+ public static void Main ()
+ {
+ Method1 ();
+ Method2 ();
+ Method3 ();
+ }
+
+ [Kept]
+ [KeptInitializerData]
+ static void Method1 ()
+ {
+ Helper (new [] {1, 2, 3});
+ Helper (new [] {1, 2, 3, 4});
+ Helper (new [] {3, 4, 5});
+ }
+
+ [Kept]
+ [KeptInitializerData]
+ static void Method2 ()
+ {
+ Helper (new [] {10, 11, 12});
+ }
+
+ [Kept]
+ [KeptInitializerData]
+ static void Method3 ()
+ {
+ Helper (new [] {10, 11, 12});
+ }
+
+ [Kept]
+ static void Helper<T> (T [] arr)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/InstantiatedTypeWithOverridesFromObject.cs b/test/Mono.Linker.Tests.Cases/Basic/InstantiatedTypeWithOverridesFromObject.cs
new file mode 100644
index 000000000..aca4cf892
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/InstantiatedTypeWithOverridesFromObject.cs
@@ -0,0 +1,44 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ public class InstantiatedTypeWithOverridesFromObject {
+ public static void Main ()
+ {
+ var f = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ ~Foo ()
+ {
+ // Finalize shouldn't be empty
+ DoCleanupStuff ();
+ }
+
+ [Kept]
+ void DoCleanupStuff ()
+ {
+ }
+
+ [Kept]
+ public override bool Equals (object obj)
+ {
+ return false;
+ }
+
+ [Kept]
+ public override string ToString ()
+ {
+ return null;
+ }
+
+ [Kept]
+ public override int GetHashCode ()
+ {
+ return 0;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/InterfaceMethodImplementedOnBaseClassDoesNotGetStripped.cs b/test/Mono.Linker.Tests.Cases/Basic/InterfaceMethodImplementedOnBaseClassDoesNotGetStripped.cs
new file mode 100644
index 000000000..fa0b762a8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/InterfaceMethodImplementedOnBaseClassDoesNotGetStripped.cs
@@ -0,0 +1,37 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class InterfaceMethodImplementedOnBaseClassDoesNotGetStripped {
+ public static void Main ()
+ {
+ I1 i1 = new Derived ();
+ i1.Used ();
+ }
+
+ public interface I1 {
+ void Unused ();
+
+ [Kept]
+ void Used ();
+ }
+
+ [KeptMember (".ctor()")]
+ public class Base {
+ public void Unused ()
+ {
+ }
+
+ [Kept]
+ public void Used ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ [KeptInterface (typeof (I1))]
+ public class Derived : Base, I1 {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/MultiLevelNestedClassesAllRemovedWhenNonUsed.cs b/test/Mono.Linker.Tests.Cases/Basic/MultiLevelNestedClassesAllRemovedWhenNonUsed.cs
new file mode 100644
index 000000000..dd5f8628e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/MultiLevelNestedClassesAllRemovedWhenNonUsed.cs
@@ -0,0 +1,19 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class MultiLevelNestedClassesAllRemovedWhenNonUsed {
+ public static void Main ()
+ {
+ }
+
+ public class A {
+ public class AB {
+ public class ABC {
+ }
+
+ public class ABD {
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/NestedDelegateInvokeMethodsPreserved.cs b/test/Mono.Linker.Tests.Cases/Basic/NestedDelegateInvokeMethodsPreserved.cs
new file mode 100644
index 000000000..c3e231781
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/NestedDelegateInvokeMethodsPreserved.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class NestedDelegateInvokeMethodsPreserved {
+ [Kept]
+ static B.Delegate @delegate;
+
+ static void Main ()
+ {
+ System.GC.KeepAlive (@delegate);
+ }
+
+ [Kept]
+ public class B {
+ [Kept]
+ [KeptMember ("Invoke()")]
+ [KeptMember ("BeginInvoke(System.AsyncCallback,System.Object)")]
+ [KeptMember ("EndInvoke(System.IAsyncResult)")]
+ [KeptMember (".ctor(System.Object,System.IntPtr)")]
+ [KeptBaseType (typeof (System.MulticastDelegate))]
+ public delegate void Delegate ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/NeverInstantiatedTypeWithOverridesFromObject.cs b/test/Mono.Linker.Tests.Cases/Basic/NeverInstantiatedTypeWithOverridesFromObject.cs
new file mode 100644
index 000000000..5303fe69f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/NeverInstantiatedTypeWithOverridesFromObject.cs
@@ -0,0 +1,38 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ public class NeverInstantiatedTypeWithOverridesFromObject {
+ public static void Main ()
+ {
+ typeof (Foo).ToString ();
+ }
+
+ [Kept]
+ class Foo {
+ ~Foo ()
+ {
+ // Finalize shouldn't be empty
+ DoCleanupStuff ();
+ }
+
+ void DoCleanupStuff ()
+ {
+ }
+
+ public override bool Equals (object obj)
+ {
+ return false;
+ }
+
+ public override string ToString ()
+ {
+ return null;
+ }
+
+ public override int GetHashCode ()
+ {
+ return 0;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UninvokedInterfaceMemberGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UninvokedInterfaceMemberGetsRemoved.cs
new file mode 100644
index 000000000..fb03b0f6d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UninvokedInterfaceMemberGetsRemoved.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UninvokedInterfaceMemberGetsRemoved {
+ public static void Main ()
+ {
+ I i = new B ();
+ var tmp = i.ToString ();
+ }
+
+ [Kept]
+ interface I {
+ void Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (I))]
+ class B : I {
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedClassGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedClassGetsRemoved.cs
new file mode 100644
index 000000000..85d60e33d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedClassGetsRemoved.cs
@@ -0,0 +1,10 @@
+namespace Mono.Linker.Tests.Cases.Basic {
+ public class UnusedClassGetsRemoved {
+ public static void Main ()
+ {
+ }
+ }
+
+ class Unused {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedDelegateGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedDelegateGetsRemoved.cs
new file mode 100644
index 000000000..d366e718e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedDelegateGetsRemoved.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UnusedDelegateGetsRemoved {
+ static void Main ()
+ {
+ }
+
+ public delegate void Foo ();
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedEnumGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedEnumGetsRemoved.cs
new file mode 100644
index 000000000..e646cfe63
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedEnumGetsRemoved.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UnusedEnumGetsRemoved {
+ static void Main ()
+ {
+ }
+
+ enum Unused {
+ One,
+ Two,
+ Three
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedEventGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedEventGetsRemoved.cs
new file mode 100644
index 000000000..ed9279d08
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedEventGetsRemoved.cs
@@ -0,0 +1,19 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UnusedEventGetsRemoved {
+ public static void Main ()
+ {
+ var tmp = new Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ public class Foo
+ {
+ public delegate void CustomDelegate ();
+
+ public event CustomDelegate Bar;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedFieldGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedFieldGetsRemoved.cs
new file mode 100644
index 000000000..6edcf5729
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedFieldGetsRemoved.cs
@@ -0,0 +1,20 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UnusedFieldGetsRemoved {
+ public static void Main ()
+ {
+ new B ().Method ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ public int _unused;
+
+ [Kept]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedFieldsOfStructsAreKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedFieldsOfStructsAreKept.cs
new file mode 100644
index 000000000..a4443a7ff
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedFieldsOfStructsAreKept.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ public class UnusedFieldsOfStructsAreKept {
+ public static void Main ()
+ {
+ A a = new A ();
+ PreventCompilerOptimization (a);
+ }
+
+ [Kept]
+ static void PreventCompilerOptimization (A a)
+ {
+ }
+
+ [Kept]
+ struct A {
+ [Kept]
+ private int UnusedField1;
+ [Kept]
+ private int UnusedField2;
+
+ public void UnusedMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedMethodGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedMethodGetsRemoved.cs
new file mode 100644
index 000000000..eaded4de5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedMethodGetsRemoved.cs
@@ -0,0 +1,22 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UnusedMethodGetsRemoved {
+ public static void Main ()
+ {
+ new UnusedMethodGetsRemoved.B ().Method ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ public void Unused ()
+ {
+ }
+
+ [Kept]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedNestedClassGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedNestedClassGetsRemoved.cs
new file mode 100644
index 000000000..7ff2fc3a6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedNestedClassGetsRemoved.cs
@@ -0,0 +1,11 @@
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ public class UnusedNestedClassGetsRemoved {
+ public static void Main ()
+ {
+ }
+
+ class Unused {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedPropertyGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedPropertyGetsRemoved.cs
new file mode 100644
index 000000000..63d82842e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedPropertyGetsRemoved.cs
@@ -0,0 +1,20 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UnusedPropertyGetsRemoved {
+ public static void Main ()
+ {
+ new UnusedPropertyGetsRemoved.B ().Method ();
+ }
+
+ [KeptMember(".ctor()")]
+ class B {
+ public int Unused { get; set; }
+
+ [Kept]
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UnusedPropertySetterRemoved.cs b/test/Mono.Linker.Tests.Cases/Basic/UnusedPropertySetterRemoved.cs
new file mode 100644
index 000000000..9bf680e77
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UnusedPropertySetterRemoved.cs
@@ -0,0 +1,17 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UnusedPropertySetterRemoved {
+ public static void Main ()
+ {
+ var val = new UnusedPropertySetterRemoved.B ().PartiallyUsed;
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept] // FIXME: Should be removed
+ [KeptBackingField]
+ public int PartiallyUsed { [Kept] get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedEnumIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedEnumIsKept.cs
new file mode 100644
index 000000000..5320ce63d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedEnumIsKept.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UsedEnumIsKept {
+ static void Main ()
+ {
+ // Use all of the values in case we implement a feature in the future that removes unused values
+ HelperAsEnum (Used.One);
+ HelperAsEnum (Used.Two);
+ HelperAsObject (Used.Three);
+ }
+
+ [Kept]
+ static void HelperAsEnum (Used arg)
+ {
+ }
+
+ [Kept]
+ static void HelperAsObject (object arg)
+ {
+ }
+
+ [Kept]
+ [KeptMember ("value__")]
+ [KeptBaseType (typeof(Enum))]
+ enum Used {
+ [Kept]
+ One,
+
+ [Kept]
+ Two,
+
+ [Kept]
+ Three
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs
new file mode 100644
index 000000000..0ff3cd573
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedEventIsKept.cs
@@ -0,0 +1,45 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ [KeptDelegateCacheField ("0")]
+ [KeptDelegateCacheField ("1")]
+ class UsedEventIsKept {
+ public static void Main ()
+ {
+ var tmp = new Foo ();
+
+ tmp.Bar += Tmp_Bar;
+ tmp.Fire ();
+ tmp.Bar -= Tmp_Bar;
+ }
+
+ [Kept]
+ private static void Tmp_Bar ()
+ {
+ }
+
+ [KeptMember (".ctor()")]
+ public class Foo {
+ [Kept]
+ [KeptBaseType (typeof(MulticastDelegate))]
+ [KeptMember (".ctor(System.Object,System.IntPtr)")]
+ [KeptMember ("Invoke()")]
+ [KeptMember ("BeginInvoke(System.AsyncCallback,System.Object)")]
+ [KeptMember ("EndInvoke(System.IAsyncResult)")]
+ public delegate void CustomDelegate ();
+
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event CustomDelegate Bar;
+
+ [Kept]
+ public void Fire ()
+ {
+ Bar ();
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs
new file mode 100644
index 000000000..828a76dac
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsKept.cs
@@ -0,0 +1,48 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ [KeptDelegateCacheField ("0")]
+ class UsedEventOnInterfaceIsKept {
+ static void Main ()
+ {
+ IFoo bar = new Bar ();
+ IFoo jar = new Jar ();
+
+ bar.Ping += Bar_Ping;
+ }
+
+ [Kept]
+ private static void Bar_Ping (object sender, EventArgs e)
+ {
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ event EventHandler Ping;
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class Bar : IFoo {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event EventHandler Ping;
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class Jar : IFoo {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event EventHandler Ping;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs
new file mode 100644
index 000000000..edff204d6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs
@@ -0,0 +1,38 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ [KeptDelegateCacheField ("0")]
+ class UsedEventOnInterfaceIsRemovedWhenUsedFromClass {
+ static void Main ()
+ {
+ var bar = new Bar ();
+ var jar = new Jar ();
+
+ bar.Ping += Bar_Ping;
+ }
+
+ [Kept]
+ private static void Bar_Ping (object sender, EventArgs e)
+ {
+ }
+
+ interface IFoo {
+ event EventHandler Ping;
+ }
+
+ [KeptMember (".ctor()")]
+ class Bar : IFoo {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event EventHandler Ping;
+ }
+
+ [KeptMember (".ctor()")]
+ class Jar : IFoo {
+ public event EventHandler Ping;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedInterfaceIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedInterfaceIsKept.cs
new file mode 100644
index 000000000..e399d2c9b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedInterfaceIsKept.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic
+{
+ class UsedInterfaceIsKept
+ {
+ public static void Main ()
+ {
+ A a = new A ();
+ var t = typeof (I).ToString();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (I))]
+ [KeptMember (".ctor()")]
+ class A : I
+ {
+ }
+
+ [Kept]
+ interface I
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedPropertyIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedPropertyIsKept.cs
new file mode 100644
index 000000000..8adc71f27
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedPropertyIsKept.cs
@@ -0,0 +1,19 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic {
+ class UsedPropertyIsKept {
+ public static void Main ()
+ {
+ var obj = new B ();
+ obj.Prop = 1;
+ var val = obj.Prop;
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept]
+ [KeptBackingField]
+ public int Prop { [Kept] get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Basic/UsedStructIsKept.cs b/test/Mono.Linker.Tests.Cases/Basic/UsedStructIsKept.cs
new file mode 100644
index 000000000..4af518fed
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Basic/UsedStructIsKept.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Basic
+{
+ class UsedStructIsKept {
+ public static void Main()
+ {
+ A a;
+ a.MethodVerifiedByKeptMember ();
+ }
+
+ [Kept]
+ // This KeptMember is here to make sure the test framework's support of KeptMember on value types is working correctly
+ [KeptMember ("MethodVerifiedByKeptMember()")]
+ struct A {
+ public void MethodVerifiedByKeptMember ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/CommandLine/Dependencies/ResponseFilesWork.rsp b/test/Mono.Linker.Tests.Cases/CommandLine/Dependencies/ResponseFilesWork.rsp
new file mode 100644
index 000000000..e4a075582
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CommandLine/Dependencies/ResponseFilesWork.rsp
@@ -0,0 +1 @@
+--used-attrs-only true \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/CommandLine/ResponseFilesWork.cs b/test/Mono.Linker.Tests.Cases/CommandLine/ResponseFilesWork.cs
new file mode 100644
index 000000000..6f65a2d52
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CommandLine/ResponseFilesWork.cs
@@ -0,0 +1,25 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CommandLine {
+ /// <summary>
+ /// This test will use only keep used attributes, which is disabled by default, to infer that the rsp file worked
+ /// </summary>
+ [SetupLinkerResponseFileAttribute ("Dependencies/ResponseFilesWork.rsp")]
+ public class ResponseFilesWork {
+ public static void Main ()
+ {
+ new Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [Foo]
+ class Bar {
+ }
+
+ class FooAttribute : Attribute {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/CoreLink/CanIncludeI18nAssemblies.cs b/test/Mono.Linker.Tests.Cases/CoreLink/CanIncludeI18nAssemblies.cs
new file mode 100644
index 000000000..28223435e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CoreLink/CanIncludeI18nAssemblies.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CoreLink {
+ [SetupLinkerCoreAction ("link")]
+ [Il8n ("all")]
+
+ // i18n assemblies should only be included when processing mono class libs. By forcing this test to use mcs,
+ // we can ensure the test will be ignored when the test runs against .net fw assemblies.
+ [SetupCSharpCompilerToUse ("mcs")]
+
+ [KeptAssembly ("I18N.dll")]
+ [KeptAssembly ("I18N.CJK.dll")]
+ [KeptAssembly ("I18N.MidEast.dll")]
+ [KeptAssembly ("I18N.Other.dll")]
+ [KeptAssembly ("I18N.Rare.dll")]
+ [KeptAssembly ("I18N.West.dll")]
+
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ public class CanIncludeI18nAssemblies {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/CoreLink/CopyOfCoreLibrariesKeepsUnusedTypes.cs b/test/Mono.Linker.Tests.Cases/CoreLink/CopyOfCoreLibrariesKeepsUnusedTypes.cs
new file mode 100644
index 000000000..bc1fd3681
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CoreLink/CopyOfCoreLibrariesKeepsUnusedTypes.cs
@@ -0,0 +1,20 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CoreLink
+{
+ [SetupLinkerCoreAction ("copy")]
+
+ [KeptAssembly ("mscorlib.dll")]
+ [KeptAllTypesAndMembersInAssembly ("mscorlib.dll")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ class CopyOfCoreLibrariesKeepsUnusedTypes
+ {
+ public static void Main()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/CoreLink/DelegateAndMulticastDelegateKeepInstantiatedReqs.cs b/test/Mono.Linker.Tests.Cases/CoreLink/DelegateAndMulticastDelegateKeepInstantiatedReqs.cs
new file mode 100644
index 000000000..22419a6d6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CoreLink/DelegateAndMulticastDelegateKeepInstantiatedReqs.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Runtime.Serialization;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CoreLink {
+ /// <summary>
+ /// Delegate and is created from
+ /// </summary>
+ [SetupLinkerCoreAction ("link")]
+ [KeptBaseOnTypeInAssembly ("mscorlib.dll", typeof (MulticastDelegate), "mscorlib.dll", typeof (Delegate))]
+
+ // Check a couple override methods to verify they were not removed
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (MulticastDelegate), "GetHashCode()")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (MulticastDelegate), "Equals(System.Object)")]
+
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (Delegate), "GetHashCode()")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (Delegate), "Equals(System.Object)")]
+ [KeptInterfaceOnTypeInAssembly("mscorlib.dll", typeof (Delegate), "mscorlib.dll", typeof (ICloneable))]
+ [KeptInterfaceOnTypeInAssembly("mscorlib.dll", typeof (Delegate), "mscorlib.dll", typeof (ISerializable))]
+
+ // Fails due to Runtime critical type System.Reflection.CustomAttributeData not found.
+ [SkipPeVerify(SkipPeVerifyForToolchian.Pedump)]
+ public class DelegateAndMulticastDelegateKeepInstantiatedReqs {
+ public static void Main ()
+ {
+ typeof (MulticastDelegate).ToString ();
+
+ // Cause the interfaces to be marked in order to eliminate the possibility of them being removed
+ // due to no code path marking the interface type
+ typeof (ISerializable).ToString ();
+ typeof (ICloneable).ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedTypeWithOverridesFromObject.cs b/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedTypeWithOverridesFromObject.cs
new file mode 100644
index 000000000..0af5194e8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CoreLink/InstantiatedTypeWithOverridesFromObject.cs
@@ -0,0 +1,48 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CoreLink {
+ [SetupLinkerCoreAction ("link")]
+ // Need to skip due to `Runtime critical type System.Reflection.CustomAttributeData not found` failure
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ public class InstantiatedTypeWithOverridesFromObject {
+ public static void Main ()
+ {
+ var f = new Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ ~Foo ()
+ {
+ // Finalize shouldn't be empty
+ DoCleanupStuff ();
+ }
+
+ [Kept]
+ void DoCleanupStuff ()
+ {
+ }
+
+ [Kept]
+ public override bool Equals (object obj)
+ {
+ return false;
+ }
+
+ [Kept]
+ public override string ToString ()
+ {
+ return null;
+ }
+
+ [Kept]
+ public override int GetHashCode ()
+ {
+ return 0;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedMethods.cs b/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedMethods.cs
new file mode 100644
index 000000000..5a39b04aa
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedMethods.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections;
+using System.IO;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CoreLink
+{
+ [SetupLinkerCoreAction ("link")]
+
+ [KeptAssembly ("mscorlib.dll")]
+ [KeptMemberInAssembly ("mscorlib.dll", typeof (Stack), ".ctor(System.Int32)", "Pop()", "Push(System.Object)")]
+ // We can't check everything that should be removed, but we should be able to check a few niche things that
+ // we known should be removed which will at least verify that the core library was processed
+ [RemovedMemberInAssembly ("mscorlib.dll", typeof (Stack), ".ctor(System.Collections.ICollection)")]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ class LinkingOfCoreLibrariesRemovesUnusedMethods {
+ public static void Main()
+ {
+ Stack stack = new Stack (2);
+ stack.Push (1);
+ var val = stack.Pop ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedTypes.cs b/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedTypes.cs
new file mode 100644
index 000000000..2ccbea396
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CoreLink/LinkingOfCoreLibrariesRemovesUnusedTypes.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CoreLink {
+ [SetupLinkerCoreAction ("link")]
+ [Reference("System.dll")]
+
+ [KeptAssembly ("mscorlib.dll")]
+ [KeptAssembly("System.dll")]
+ // We can't check everything that should be removed, but we should be able to check a few niche things that
+ // we known should be removed which will at least verify that the core library was processed
+ [KeptTypeInAssembly ("mscorlib.dll", typeof (System.Collections.Generic.IEnumerable<>))]
+ [KeptTypeInAssembly ("System.dll", typeof (System.Collections.Generic.SortedList<,>))]
+
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (System.Resources.ResourceWriter))]
+ [RemovedTypeInAssembly ("System.dll", typeof (System.Collections.Generic.SortedDictionary<,>))]
+
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+
+ // All sorts of stuff is flagged as invalid even in the original System.dll and System.Configuration.dll for mono class libraries
+ [SkipPeVerify("System.dll")]
+ [SkipPeVerify("System.Configuration.dll")]
+ // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
+ // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
+ // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
+ [SkipPeVerify ("System.Core.dll")]
+ class LinkingOfCoreLibrariesRemovesUnusedTypes {
+ public static void Main ()
+ {
+ // Use something from system that would normally be removed if we didn't use it
+ OtherMethods2 (new SortedList<string, string>());
+ }
+
+ [Kept]
+ static void OtherMethods2 (SortedList<string, string> list)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/CoreLink/NeverInstantiatedTypeWithOverridesFromObject.cs b/test/Mono.Linker.Tests.Cases/CoreLink/NeverInstantiatedTypeWithOverridesFromObject.cs
new file mode 100644
index 000000000..9d1627aff
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CoreLink/NeverInstantiatedTypeWithOverridesFromObject.cs
@@ -0,0 +1,42 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CoreLink {
+ [SetupLinkerCoreAction ("link")]
+ // Need to skip due to `Runtime critical type System.Reflection.CustomAttributeData not found` failure
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ public class NeverInstantiatedTypeWithOverridesFromObject {
+ public static void Main ()
+ {
+ typeof (Foo).ToString ();
+ }
+
+ [Kept]
+ class Foo {
+ ~Foo ()
+ {
+ // Finalize shouldn't be empty
+ DoCleanupStuff ();
+ }
+
+ void DoCleanupStuff ()
+ {
+ }
+
+ public override bool Equals (object obj)
+ {
+ return false;
+ }
+
+ public override string ToString ()
+ {
+ return null;
+ }
+
+ public override int GetHashCode ()
+ {
+ return 0;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/CoreLink/NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs b/test/Mono.Linker.Tests.Cases/CoreLink/NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs
new file mode 100644
index 000000000..cc6757e6e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/CoreLink/NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs
@@ -0,0 +1,41 @@
+using System.Diagnostics;
+using System.Security;
+using System.Security.Permissions;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.CoreLink {
+ [SetupLinkerCoreAction ("link")]
+ [SetupLinkerArgument ("--strip-security", "true")]
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ [Reference ("System.dll")]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SecurityPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (PermissionSetAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (ReflectionPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (RegistryPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (StrongNameIdentityPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (CodeAccessSecurityAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (EnvironmentPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (FileIOPermissionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (HostProtectionAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SecurityCriticalAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SecuritySafeCriticalAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SuppressUnmanagedCodeSecurityAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (SecurityRulesAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (AllowPartiallyTrustedCallersAttribute))]
+ [RemovedTypeInAssembly ("mscorlib.dll", typeof (UnverifiableCodeAttribute))]
+ // Fails with `Runtime critical type System.Reflection.CustomAttributeData not found` which is a known short coming
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ [SkipPeVerify ("System.dll")]
+ // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
+ // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
+ // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
+ [SkipPeVerify ("System.Core.dll")]
+ public class NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries {
+ public static void Main ()
+ {
+ // Use something that has security attributes to make this test more meaningful
+ var process = new Process ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/CorrectOverloadedMethodGetsStrippedInGenericClass.cs b/test/Mono.Linker.Tests.Cases/Generics/CorrectOverloadedMethodGetsStrippedInGenericClass.cs
new file mode 100644
index 000000000..362c3bb3d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/CorrectOverloadedMethodGetsStrippedInGenericClass.cs
@@ -0,0 +1,37 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ class CorrectOverloadedMethodGetsStrippedInGenericClass {
+ public static void Main ()
+ {
+ // Call overloaded method through the abstract base class
+ GenericClassWithTwoOverloadedAbstractMethods<float> item = new SpecializedClassWithTwoOverloadedVirtualMethods ();
+ item.OverloadedMethod (5);
+ }
+
+ [KeptMember (".ctor()")]
+ public abstract class GenericClassWithTwoOverloadedAbstractMethods<T> {
+ public abstract string OverloadedMethod (T thing); // Don't call this one, it should be stripped
+
+ [Kept]
+ public abstract string OverloadedMethod (int thing); // Call to this should preserve the overriden one
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (GenericClassWithTwoOverloadedAbstractMethods<System.Single>))]
+ public class SpecializedClassWithTwoOverloadedVirtualMethods : GenericClassWithTwoOverloadedAbstractMethods<float> {
+ // Don't call this one, it should be stripped
+ public override string OverloadedMethod (float thing)
+ {
+ return "first";
+ }
+
+ // Don't call this one, but it shouldn't be stripped because the method it overrides is invoked
+ [Kept]
+ public override string OverloadedMethod (int thing)
+ {
+ return "second";
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Generics/DerivedClassWithMethodOfSameNameAsBaseButDifferentNumberOfGenericParametersUnusedBaseWillGetStripped.cs b/test/Mono.Linker.Tests.Cases/Generics/DerivedClassWithMethodOfSameNameAsBaseButDifferentNumberOfGenericParametersUnusedBaseWillGetStripped.cs
new file mode 100644
index 000000000..b13f8267e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/DerivedClassWithMethodOfSameNameAsBaseButDifferentNumberOfGenericParametersUnusedBaseWillGetStripped.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ class DerivedClassWithMethodOfSameNameAsBaseButDifferentNumberOfGenericParametersUnusedBaseWillGetStripped {
+ public static void Main (string [] args)
+ {
+ MyDerived obj = new MyDerived ();
+ obj.Method<int, int> (1);
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class MyBase {
+ public virtual T Method<T> (T arg1)
+ {
+ return arg1;
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (MyBase))]
+ class MyDerived : MyBase {
+ [Kept]
+ public virtual T Method<T, K> (T arg1)
+ {
+ return arg1;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/GenericInstanceInterfaceMethodImplementedWithDifferentGenericArgumentNameDoesNotGetStripped.cs b/test/Mono.Linker.Tests.Cases/Generics/GenericInstanceInterfaceMethodImplementedWithDifferentGenericArgumentNameDoesNotGetStripped.cs
new file mode 100644
index 000000000..4a912d678
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/GenericInstanceInterfaceMethodImplementedWithDifferentGenericArgumentNameDoesNotGetStripped.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ class GenericInstanceInterfaceMethodImplementedWithDifferentGenericArgumentNameDoesNotGetStripped {
+ public static void Main ()
+ {
+ ISomething it = new Concrete ();
+ it.ShouldNotGetStripped<int> ();
+ }
+
+ [Kept]
+ public class GenericType<T> {
+ }
+
+ public interface ISomething {
+ [Kept]
+ GenericType<TInInterface> ShouldNotGetStripped<TInInterface> ();
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (ISomething))]
+ public class Concrete : ISomething {
+ [Kept]
+ public GenericType<TInConcrete> ShouldNotGetStripped<TInConcrete> ()
+ {
+ throw new System.Exception ();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameter.cs b/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameter.cs
new file mode 100644
index 000000000..5f8a4389e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameter.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ class MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameter {
+ public static void Main (string [] args)
+ {
+ Derived<int, int> tmp = new Derived<int, int> ();
+ tmp.Method<int> (null);
+ }
+
+ [KeptMember (".ctor()")]
+ public abstract class Base<TSource> {
+ [Kept]
+ public abstract TResult1 Method<TResult1> (IDictionary<TSource, TResult1> arg);
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base<>), "TResult1")]
+ public class Derived<TSource, TResult1> : Base<TResult1> {
+ [Kept]
+ public override TResult2 Method<TResult2> (IDictionary<TResult1, TResult2> arg)
+ {
+ return default (TResult2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase.cs b/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase.cs
new file mode 100644
index 000000000..37d1305dc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ class MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase {
+ public static void Main (string [] args)
+ {
+ Derived<int, int> tmp = new Derived<int, int> ();
+ tmp.Method<int> (null);
+ }
+
+ [Kept]
+ public class Base<TSource> {
+
+ [KeptMember (".ctor()")]
+ public abstract class Nested {
+ [Kept]
+ public abstract TResult1 Method<TResult1> (IDictionary<TSource, TResult1> arg);
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base<>.Nested), "TResult1")]
+ public class Derived<TSource, TResult1> : Base<TResult1>.Nested {
+ [Kept]
+ public override TResult2 Method<TResult2> (IDictionary<TResult1, TResult2> arg)
+ {
+ return default (TResult2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase2.cs b/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase2.cs
new file mode 100644
index 000000000..f6e1370a3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase2.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ class MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase2 {
+ public static void Main (string [] args)
+ {
+ Derived<int, int> tmp = new Derived<int, int> ();
+ tmp.Method<int> (null);
+ }
+
+ [Kept]
+ public class Base<TSource> {
+
+ [KeptMember (".ctor()")]
+ public abstract class Nested<T1, T2, T3> {
+ [Kept]
+ public abstract TResult1 Method<TResult1> (IDictionary<TSource, TResult1> arg);
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base<>.Nested<,,>), "TResult1", typeof (int), typeof (int), typeof (string))]
+ public class Derived<TSource, TResult1> : Base<TResult1>.Nested<int, int, string> {
+ [Kept]
+ public override TResult2 Method<TResult2> (IDictionary<TResult1, TResult2> arg)
+ {
+ return default (TResult2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/NewConstraintOnClass.cs b/test/Mono.Linker.Tests.Cases/Generics/NewConstraintOnClass.cs
new file mode 100644
index 000000000..2d644e5c3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/NewConstraintOnClass.cs
@@ -0,0 +1,37 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics
+{
+ public class NewConstraintOnClass
+ {
+ public static void Main ()
+ {
+ var g1 = new G1<G1Ctor> ();
+ }
+
+ class G1Ctor
+ {
+ static readonly int field = 1;
+
+ [Kept]
+ public G1Ctor ()
+ {
+ }
+
+ public G1Ctor (int a)
+ {
+ }
+
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class G1<T> where T : G1Ctor, new ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Generics/OverrideWithAnotherVirtualMethodOfSameNameWithDifferentParameterType.cs b/test/Mono.Linker.Tests.Cases/Generics/OverrideWithAnotherVirtualMethodOfSameNameWithDifferentParameterType.cs
new file mode 100644
index 000000000..ba81282b8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/OverrideWithAnotherVirtualMethodOfSameNameWithDifferentParameterType.cs
@@ -0,0 +1,34 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ class OverrideWithAnotherVirtualMethodOfSameNameWithDifferentParameterType {
+ public static void Main (string [] args)
+ {
+ new Derived<double, int> ().Method (1.0);
+ }
+
+ [KeptMember (".ctor()")]
+ public class Base<S> {
+ [Kept]
+ public virtual S Method (S arg)
+ {
+ return arg;
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base<>), "K")]
+ public class Derived<K, S> : Base<K> {
+ [Kept]
+ public override K Method (K arg)
+ {
+ return arg;
+ }
+
+ public virtual S Method (S arg)
+ {
+ return arg;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodInGenericClassIsNotStripped.cs b/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodInGenericClassIsNotStripped.cs
new file mode 100644
index 000000000..908e0d50d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodInGenericClassIsNotStripped.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ public class UsedOverloadedGenericMethodInGenericClassIsNotStripped {
+ public static void Main ()
+ {
+ B<int>.Method (true);
+ }
+
+ class B<TBase> {
+ [Kept]
+ public static void Method<T> (T value)
+ {
+ }
+
+ public static void Method (TBase value)
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodInstanceInGenericClassIsNotStripped.cs b/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodInstanceInGenericClassIsNotStripped.cs
new file mode 100644
index 000000000..a565d4cf5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodInstanceInGenericClassIsNotStripped.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ public class UsedOverloadedGenericMethodInstanceInGenericClassIsNotStripped {
+ public static void Main ()
+ {
+ B<int>.Method (1);
+ }
+
+ class B<TBase> {
+ public static void Method<T> (T value)
+ {
+ }
+
+ [Kept]
+ public static void Method (TBase value)
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodWithNoParametersIsNotStripped.cs b/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodWithNoParametersIsNotStripped.cs
new file mode 100644
index 000000000..52e1ff7b2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Generics/UsedOverloadedGenericMethodWithNoParametersIsNotStripped.cs
@@ -0,0 +1,27 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Generics {
+ public class UsedOverloadedGenericMethodWithNoParametersIsNotStripped {
+ public static void Main ()
+ {
+ B.Call<string, int> ();
+ }
+
+ public class B {
+ public static void Method<T> ()
+ {
+ }
+
+ [Kept]
+ public static void Method<TKey, TValue> ()
+ {
+ }
+
+ [Kept]
+ public static void Call<TKey, TValue> ()
+ {
+ B.Method<TKey, TValue> ();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfAbstractIsKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfAbstractIsKept.cs
new file mode 100644
index 000000000..9cbb14504
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfAbstractIsKept.cs
@@ -0,0 +1,42 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval {
+ public class OverrideOfAbstractIsKept {
+ public static void Main ()
+ {
+ Base b = HelperToMarkFooAndRequireBase ();
+ b.Method ();
+ }
+
+ [Kept]
+ static Foo HelperToMarkFooAndRequireBase ()
+ {
+ return null;
+ }
+
+ [Kept]
+ abstract class Base {
+ [Kept]
+ public abstract void Method ();
+ }
+
+ [Kept]
+ [KeptBaseType (typeof(Base))]
+ abstract class Base2 : Base {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base2))]
+ abstract class Base3 : Base2 {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base3))]
+ class Foo : Base3 {
+ [Kept]
+ public override void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved.cs
new file mode 100644
index 000000000..6277e8338
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved.cs
@@ -0,0 +1,33 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval {
+ public class OverrideOfVirtualCanBeRemoved {
+ public static void Main ()
+ {
+ Base b = HelperToMarkFooAndRequireBase ();
+ b.Method ();
+ }
+
+ [Kept]
+ static Foo HelperToMarkFooAndRequireBase ()
+ {
+ return null;
+ }
+
+ [Kept]
+ class Base {
+ [Kept]
+ public virtual void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base))]
+ class Foo : Base {
+ public override void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved2.cs
new file mode 100644
index 000000000..4bb4df93c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved2.cs
@@ -0,0 +1,46 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval {
+ public class OverrideOfVirtualCanBeRemoved2 {
+ public static void Main ()
+ {
+ Base b = HelperToMarkFooAndRequireBase ();
+ b.Method ();
+ }
+
+ [Kept]
+ static Foo HelperToMarkFooAndRequireBase ()
+ {
+ return null;
+ }
+
+ [Kept]
+ abstract class Base {
+ [Kept]
+ public abstract void Method ();
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base))]
+ abstract class Base2 : Base
+ {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base2))]
+ class Base3 : Base2 {
+ [Kept]
+ public override void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base3))]
+ class Foo : Base3 {
+ public override void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved3.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved3.cs
new file mode 100644
index 000000000..1f376e05c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideOfVirtualCanBeRemoved3.cs
@@ -0,0 +1,45 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval {
+ public class OverrideOfVirtualCanBeRemoved3 {
+ public static void Main ()
+ {
+ HelperToMarkFoo2AndRequireBase();
+ Base b = HelperToMarkFooAndRequireBase ();
+ b.Method ();
+ }
+
+ [Kept]
+ static Foo HelperToMarkFooAndRequireBase ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static Foo2 HelperToMarkFoo2AndRequireBase ()
+ {
+ return null;
+ }
+
+ [Kept]
+ class Base {
+ [Kept]
+ public virtual void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base))]
+ class Foo : Base {
+ public override void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Foo))]
+ class Foo2 : Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideThatAlsoFulfilsInterface.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideThatAlsoFulfilsInterface.cs
new file mode 100644
index 000000000..428310dad
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/OverrideThatAlsoFulfilsInterface.cs
@@ -0,0 +1,59 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval {
+ public class OverrideThatAlsoFulfilsInterface {
+ public static void Main ()
+ {
+ Base b = HelperToMarkFooAndRequireBase ();
+ b.Method ();
+
+ MethodToUseTheInterface ();
+ }
+
+ [Kept]
+ static void MethodToUseTheInterface ()
+ {
+ // Now use the interface method so that it is kept
+ IFoo f = new Bar ();
+ f.Method ();
+ }
+
+ [Kept]
+ static Foo HelperToMarkFooAndRequireBase ()
+ {
+ return null;
+ }
+
+ [Kept]
+ class Base {
+ [Kept]
+ public virtual void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class Bar : IFoo {
+ [Kept]
+ public void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base))]
+ class Foo : Base, IFoo {
+ public override void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.cs
new file mode 100644
index 000000000..d21678797
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.cs
@@ -0,0 +1,51 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval {
+ public class PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved {
+ public static void Main ()
+ {
+ Base j = new Jar ();
+ j.One ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ abstract class Base {
+ [Kept]
+ public abstract void Foo ();
+
+ [Kept]
+ public virtual void One ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base))]
+ class Bar : Base {
+ [Kept]
+ public override void Foo ()
+ {
+ }
+
+ public override void One ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ class Jar : Base {
+ [Kept]
+ public override void Foo ()
+ {
+ }
+
+ [Kept]
+ public override void One ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.xml b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.xml
new file mode 100644
index 000000000..932f34d59
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.xml
@@ -0,0 +1,7 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval.PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved/Bar">
+ <method name="Foo"/>
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.cs
new file mode 100644
index 000000000..a1ddd7c30
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.cs
@@ -0,0 +1,60 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval {
+ public class PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2 {
+ public static void Main ()
+ {
+ Base j = new Jar ();
+ j.One ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ abstract class Base {
+ [Kept]
+ public abstract void Foo ();
+
+ [Kept]
+ public abstract void One ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ abstract class Base2 : Base
+ {
+ [Kept]
+ public override void One ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base2))]
+ class Bar : Base2 {
+ [Kept]
+ public override void Foo ()
+ {
+ }
+
+ public override void One ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base2))]
+ class Jar : Base2 {
+ [Kept]
+ public override void Foo ()
+ {
+ }
+
+ [Kept]
+ public override void One ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.xml b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.xml
new file mode 100644
index 000000000..1395ed53f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/NoKeptCtor/OverrideRemoval/PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.xml
@@ -0,0 +1,7 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.AbstractClasses.NoKeptCtor.OverrideRemoval.PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2/Bar">
+ <method name="Foo"/>
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UnusedAbstractMethodRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UnusedAbstractMethodRemoved.cs
new file mode 100644
index 000000000..452493a97
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UnusedAbstractMethodRemoved.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses {
+ public class UnusedAbstractMethodRemoved {
+ public static void Main ()
+ {
+ var tmp = new B ();
+ }
+
+ [KeptMember (".ctor()")]
+ abstract class Base {
+ public abstract void Call ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ class B : Base {
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UnusedVirtualMethodRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UnusedVirtualMethodRemoved.cs
new file mode 100644
index 000000000..82f5d6729
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UnusedVirtualMethodRemoved.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses {
+ public class UnusedVirtualMethodRemoved {
+ public static void Main ()
+ {
+ var tmp = new B ();
+ }
+
+ [KeptMember (".ctor()")]
+ abstract class Base {
+ public virtual void Call ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ class B : Base {
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UsedOverrideOfAbstractMethodIsKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UsedOverrideOfAbstractMethodIsKept.cs
new file mode 100644
index 000000000..f2362aef6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UsedOverrideOfAbstractMethodIsKept.cs
@@ -0,0 +1,27 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses {
+ public class UsedOverrideOfAbstractMethodIsKept {
+ public static void Main ()
+ {
+ var tmp = new B ();
+ tmp.Call ();
+ }
+
+ [KeptMember (".ctor()")]
+ abstract class Base {
+ [Kept]
+ public abstract void Call ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ class B : Base {
+ [Kept]
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UsedOverrideOfVirtualMethodIsKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UsedOverrideOfVirtualMethodIsKept.cs
new file mode 100644
index 000000000..e27049e36
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.AbstractClasses/UsedOverrideOfVirtualMethodIsKept.cs
@@ -0,0 +1,29 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.AbstractClasses {
+ public class UsedOverrideOfVirtualMethodIsKept {
+ public static void Main ()
+ {
+ var tmp = new B ();
+ tmp.Call ();
+ }
+
+ [KeptMember (".ctor()")]
+ abstract class Base {
+ [Kept]
+ public virtual void Call ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ class B : Base {
+ [Kept]
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy.cs
new file mode 100644
index 000000000..72d30becd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy.cs
@@ -0,0 +1,13 @@
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies {
+ public class InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy {
+ public static void ToKeepReferenceAtCompileTime ()
+ {
+ }
+
+ public class A : InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.IFoo {
+ void InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.IFoo.Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.cs
new file mode 100644
index 000000000..cf093a8d7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.cs
@@ -0,0 +1,7 @@
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies {
+ public class InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link {
+ public interface IFoo {
+ void Method ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy.cs
new file mode 100644
index 000000000..62eb61d3a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy.cs
@@ -0,0 +1,13 @@
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies {
+ public class InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy {
+ public static void ToKeepReferenceAtCompileTime ()
+ {
+ }
+
+ public class A : InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link.IFoo {
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link.cs
new file mode 100644
index 000000000..a03e2708f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link.cs
@@ -0,0 +1,7 @@
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies {
+ public class InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link {
+ public interface IFoo {
+ void Method ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.cs
new file mode 100644
index 000000000..e4ca903cb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/Dependencies/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.cs
@@ -0,0 +1,10 @@
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies
+{
+ public class InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib
+ {
+ public interface IFoo
+ {
+ bool ExplicitMethod();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplementingInterfaceMethodsNested.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplementingInterfaceMethodsNested.cs
new file mode 100644
index 000000000..3a4b3b197
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplementingInterfaceMethodsNested.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class ClassImplementingInterfaceMethodsNested {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar : IFoo {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class A : IBar {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplementingInterfaceMethodsNested2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplementingInterfaceMethodsNested2.cs
new file mode 100644
index 000000000..aba1ed062
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplementingInterfaceMethodsNested2.cs
@@ -0,0 +1,39 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class ClassImplementingInterfaceMethodsNested2 {
+ public static void Main ()
+ {
+ IBar b = new A ();
+ IFoo f = b;
+ f.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ interface IBar : IFoo {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IBar))]
+ [KeptInterface (typeof (IFoo))]
+ class A : IBar {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass2.cs
new file mode 100644
index 000000000..0d7f9353e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass2.cs
@@ -0,0 +1,29 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ class ClassImplemtingInterfaceMethodsThroughBaseClass2 {
+ public static void Main ()
+ {
+ new B ();
+ IFoo i = null;
+ i.Foo ();
+ }
+
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept] // FIXME: Should be removed
+ public void Foo ()
+ {
+ }
+ }
+
+ class A : B, IFoo {
+ //my IFoo.Foo() is actually implemented by B which doesn't know about it.
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass3.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass3.cs
new file mode 100644
index 000000000..1154be592
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass3.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ class ClassImplemtingInterfaceMethodsThroughBaseClass3 {
+ public static void Main ()
+ {
+ new B ().Foo ();
+ }
+
+ interface IFoo {
+ void Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ class A : B, IFoo {
+ //my IFoo.Foo() is actually implemented by B which doesn't know about it.
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass4.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass4.cs
new file mode 100644
index 000000000..7a01c07ac
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass4.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ class ClassImplemtingInterfaceMethodsThroughBaseClass4 {
+ public static void Main ()
+ {
+ new A ().Foo ();
+ }
+
+ interface IFoo {
+ void Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (B))]
+ class A : B, IFoo {
+ //my IFoo.Foo() is actually implemented by B which doesn't know about it.
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass5.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass5.cs
new file mode 100644
index 000000000..f7ebfda35
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass5.cs
@@ -0,0 +1,27 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ class ClassImplemtingInterfaceMethodsThroughBaseClass5 {
+ public static void Main ()
+ {
+ new A ();
+ }
+
+ interface IFoo {
+ void Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ public void Foo ()
+ {
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (B))]
+ class A : B, IFoo {
+ //my IFoo.Foo() is actually implemented by B which doesn't know about it.
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass6.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass6.cs
new file mode 100644
index 000000000..1f43d756f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassImplemtingInterfaceMethodsThroughBaseClass6.cs
@@ -0,0 +1,38 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ class ClassImplemtingInterfaceMethodsThroughBaseClass6 {
+ public static void Main ()
+ {
+ B tmp = new B ();
+ IFoo i = new C ();
+ i.Foo ();
+ }
+
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept] // FIXME: Needs to be removed
+ public void Foo ()
+ {
+ }
+ }
+
+ class A : B, IFoo {
+ //my IFoo.Foo() is actually implemented by B which doesn't know about it.
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class C : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromConcreteTypeHasInterfaceMethodRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromConcreteTypeHasInterfaceMethodRemoved.cs
new file mode 100644
index 000000000..8c9212981
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromConcreteTypeHasInterfaceMethodRemoved.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType
+{
+ class ClassUsedFromConcreteTypeHasInterfaceMethodRemoved {
+ public static void Main ()
+ {
+ A a = new A ();
+ a.Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class A : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ public interface IFoo {
+ void Foo ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs
new file mode 100644
index 000000000..f754047ca
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs
@@ -0,0 +1,29 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class ClassUsedFromConcreteTypeHasInterfaceMethodRemoved2 {
+ public static void Main ()
+ {
+ A a = new A ();
+ a.Foo ();
+
+ // If IFoo is marked for any reason then all of a sudden we do need to keep IFoo on A
+ var tmp = typeof (IFoo).ToString ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class A : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ public interface IFoo {
+ void Foo ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromInterfaceHasInterfaceMethodKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromInterfaceHasInterfaceMethodKept.cs
new file mode 100644
index 000000000..a04dcb72c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ClassUsedFromInterfaceHasInterfaceMethodKept.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType
+{
+ class ClassUsedFromInterfaceHasInterfaceMethodKept {
+ public static void Main ()
+ {
+ IFoo a = new A ();
+ a.Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class A : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ public interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ExplicitInterfaceMethodWhichCreatesInstanceOfParentType.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ExplicitInterfaceMethodWhichCreatesInstanceOfParentType.cs
new file mode 100644
index 000000000..a9f3729d0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ExplicitInterfaceMethodWhichCreatesInstanceOfParentType.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class ExplicitInterfaceMethodWhichCreatesInstanceOfParentType {
+ public static void Main ()
+ {
+ IFoo b = new B ();
+ b.Method ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class B : IFoo {
+ [Kept]
+ public void Method ()
+ {
+ }
+ }
+
+ class C : IFoo {
+ void IFoo.Method () { new C (); }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter.cs
new file mode 100644
index 000000000..6a2597c8c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter.cs
@@ -0,0 +1,136 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class InterfaceMarkOrderingDoesNotMatter {
+ public static void Main ()
+ {
+ CauseAToBeMarked ().AMethod ();
+ CauseZToBeMarked ().ZMethod ();
+
+ MMarked m = new MMarked ();
+
+ B b = m;
+ Y y = m;
+ Nested.F f = m;
+
+ b.BMethod ();
+ y.YMethod ();
+ f.FMethod ();
+ }
+
+ [Kept]
+ static A CauseAToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static Z CauseZToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ interface A {
+ [Kept]
+ void AMethod ();
+ }
+
+ [Kept]
+ interface Z {
+ [Kept]
+ void ZMethod ();
+ }
+
+ [Kept]
+ interface C {
+ [Kept]
+ void CMethod ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (A))]
+ [KeptInterface (typeof (B))]
+ [KeptInterface (typeof (C))]
+ [KeptInterface (typeof (D))]
+ [KeptInterface (typeof (Nested.F))]
+ [KeptInterface (typeof (Y))]
+ [KeptInterface (typeof (Z))]
+ [KeptInterface (typeof (E))]
+ class MMarked : A, B, Y, Z, C, D, Nested.F, E {
+ [Kept]
+ public void AMethod()
+ {
+ }
+
+ [Kept]
+ public void BMethod ()
+ {
+ }
+
+ [Kept]
+ public void YMethod ()
+ {
+ }
+
+ [Kept]
+ public void ZMethod ()
+ {
+ }
+
+ [Kept]
+ public void CMethod ()
+ {
+ }
+
+ [Kept]
+ public void DMethod ()
+ {
+ }
+
+ [Kept]
+ public void FMethod ()
+ {
+ }
+
+ [Kept]
+ public void EMethod ()
+ {
+ }
+ }
+
+ [Kept]
+ public static class Nested {
+ [Kept]
+ public interface F {
+ [Kept]
+ void FMethod ();
+ }
+ }
+
+ [Kept]
+ interface B {
+ [Kept]
+ void BMethod ();
+ }
+
+ [Kept]
+ interface Y {
+ [Kept]
+ void YMethod ();
+ }
+
+ [Kept]
+ interface D {
+ [Kept]
+ void DMethod ();
+ }
+
+ [Kept]
+ interface E {
+ [Kept]
+ void EMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter.xml
new file mode 100644
index 000000000..3acce8472
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter.xml
@@ -0,0 +1,11 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.InterfaceMarkOrderingDoesNotMatter/C">
+ <method name="CMethod"/>
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.InterfaceMarkOrderingDoesNotMatter/D">
+ <method name="DMethod"/>
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.InterfaceMarkOrderingDoesNotMatter/E" preserve="methods"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter2.cs
new file mode 100644
index 000000000..1831dcd57
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter2.cs
@@ -0,0 +1,144 @@
+
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType
+{
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (InterfaceMarkOrderingDoesNotMatter2_Z.A))]
+ [KeptInterface (typeof (InterfaceMarkOrderingDoesNotMatter2_Z.B))]
+ [KeptInterface (typeof (InterfaceMarkOrderingDoesNotMatter2_Z.C))]
+ [KeptInterface (typeof (InterfaceMarkOrderingDoesNotMatter2_Z.D))]
+ [KeptInterface (typeof (InterfaceMarkOrderingDoesNotMatter2_Z.Nested.F))]
+ [KeptInterface (typeof (InterfaceMarkOrderingDoesNotMatter2_Z.Y))]
+ [KeptInterface (typeof (InterfaceMarkOrderingDoesNotMatter2_Z.Z))]
+ [KeptInterface (typeof (InterfaceMarkOrderingDoesNotMatter2_Z.E))]
+ class InterfaceMarkOrderingDoesNotMatter2_A : InterfaceMarkOrderingDoesNotMatter2_Z.A, InterfaceMarkOrderingDoesNotMatter2_Z.B, InterfaceMarkOrderingDoesNotMatter2_Z.Y,
+ InterfaceMarkOrderingDoesNotMatter2_Z.Z, InterfaceMarkOrderingDoesNotMatter2_Z.C, InterfaceMarkOrderingDoesNotMatter2_Z.D,
+ InterfaceMarkOrderingDoesNotMatter2_Z.Nested.F, InterfaceMarkOrderingDoesNotMatter2_Z.E {
+ [Kept]
+ public void AMethod()
+ {
+ }
+
+ [Kept]
+ public void BMethod ()
+ {
+ }
+
+ [Kept]
+ public void YMethod ()
+ {
+ }
+
+ [Kept]
+ public void ZMethod ()
+ {
+ }
+
+ [Kept]
+ public void CMethod ()
+ {
+ }
+
+ [Kept]
+ public void DMethod ()
+ {
+ }
+
+ [Kept]
+ public void FMethod ()
+ {
+ }
+
+ [Kept]
+ public void EMethod ()
+ {
+ }
+ }
+
+ public class InterfaceMarkOrderingDoesNotMatter2
+ {
+ public static void Main()
+ {
+ CauseAToBeMarked().AMethod();
+ CauseZToBeMarked().ZMethod();
+
+ InterfaceMarkOrderingDoesNotMatter2_A mUsedInCode = new InterfaceMarkOrderingDoesNotMatter2_A();
+
+ InterfaceMarkOrderingDoesNotMatter2_Z.B b = mUsedInCode;
+ InterfaceMarkOrderingDoesNotMatter2_Z.Y y = mUsedInCode;
+ InterfaceMarkOrderingDoesNotMatter2_Z.Nested.F f = mUsedInCode;
+
+ b.BMethod();
+ y.YMethod();
+ f.FMethod();
+ }
+
+ [Kept]
+ static InterfaceMarkOrderingDoesNotMatter2_Z.A CauseAToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static InterfaceMarkOrderingDoesNotMatter2_Z.Z CauseZToBeMarked ()
+ {
+ return null;
+ }
+ }
+
+ [Kept]
+ public class InterfaceMarkOrderingDoesNotMatter2_Z {
+ [Kept]
+ public interface A {
+ [Kept]
+ void AMethod ();
+ }
+
+ [Kept]
+ public interface Z {
+ [Kept]
+ void ZMethod ();
+ }
+
+ [Kept]
+ public interface C {
+ [Kept]
+ void CMethod ();
+ }
+
+ [Kept]
+ public static class Nested {
+ [Kept]
+ public interface F {
+ [Kept]
+ void FMethod ();
+ }
+ }
+
+ [Kept]
+ public interface B {
+ [Kept]
+ void BMethod ();
+ }
+
+ [Kept]
+ public interface Y {
+ [Kept]
+ void YMethod ();
+ }
+
+ [Kept]
+ public interface D {
+ [Kept]
+ void DMethod ();
+ }
+
+ [Kept]
+ public interface E {
+ [Kept]
+ void EMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter2.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter2.xml
new file mode 100644
index 000000000..da1a70f25
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter2.xml
@@ -0,0 +1,11 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.InterfaceMarkOrderingDoesNotMatter2_Z/C">
+ <method name="CMethod"/>
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.InterfaceMarkOrderingDoesNotMatter2_Z/D">
+ <method name="DMethod"/>
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.InterfaceMarkOrderingDoesNotMatter2_Z/E" preserve="methods"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter3.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter3.cs
new file mode 100644
index 000000000..5c658dedc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter3.cs
@@ -0,0 +1,144 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class InterfaceMarkOrderingDoesNotMatter3 {
+ public static void Main ()
+ {
+ CauseAToBeMarked ().AMethod ();
+ CauseZToBeMarked ().ZMethod ();
+ CauseBToBeMarked ().BMethod ();
+ CauseYToBeMarked ().YMethod ();
+ CauseFToBeMarked ().FMethod ();
+ var c = CauseCToBeMarked();
+ }
+
+ [Kept]
+ static A CauseAToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static Z CauseZToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static B CauseBToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static Y CauseYToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static Nested.F CauseFToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static C CauseCToBeMarked ()
+ {
+ return null;
+ }
+
+ [Kept]
+ interface A {
+ [Kept]
+ void AMethod ();
+ }
+
+ [Kept]
+ interface Z {
+ [Kept]
+ void ZMethod ();
+ }
+
+ [Kept]
+ interface C {
+ void CMethod ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (A))]
+ [KeptInterface (typeof (B))]
+ [KeptInterface (typeof (C))]
+ [KeptInterface (typeof (Nested.F))]
+ [KeptInterface (typeof (Y))]
+ [KeptInterface (typeof (Z))]
+ class MMarked : A, B, Y, Z, C, D, Nested.F, E {
+ [Kept]
+ public void AMethod()
+ {
+ }
+
+ [Kept]
+ public void BMethod ()
+ {
+ }
+
+ [Kept]
+ public void YMethod ()
+ {
+ }
+
+ [Kept]
+ public void ZMethod ()
+ {
+ }
+
+ public void CMethod ()
+ {
+ }
+
+ public void DMethod ()
+ {
+ }
+
+ [Kept]
+ public void FMethod ()
+ {
+ }
+
+ public void EMethod ()
+ {
+ }
+ }
+
+ [Kept]
+ public static class Nested {
+ [Kept]
+ public interface F {
+ [Kept]
+ void FMethod ();
+ }
+ }
+
+ [Kept]
+ interface B {
+ [Kept]
+ void BMethod ();
+ }
+
+ [Kept]
+ interface Y {
+ [Kept]
+ void YMethod ();
+ }
+
+ interface D {
+ void DMethod ();
+ }
+
+ interface E {
+ void EMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter3.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter3.xml
new file mode 100644
index 000000000..7b6a3c763
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceMarkOrderingDoesNotMatter3.xml
@@ -0,0 +1,7 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.InterfaceMarkOrderingDoesNotMatter3/MMarked">
+ <method name=".ctor"/>
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeInOtherUsedOnlyByCopiedAssembly.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeInOtherUsedOnlyByCopiedAssembly.cs
new file mode 100644
index 000000000..ba22206b3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeInOtherUsedOnlyByCopiedAssembly.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ [SetupCompileBefore ("linked.dll", new [] {typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link)})]
+ [SetupCompileBefore ("copy.dll", new [] {typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy)}, new [] {"linked.dll"})]
+
+ [SetupLinkerAction ("copy", "copy")]
+ [SetupLinkerArgument ("-a", "copy")]
+
+ [KeptTypeInAssembly ("linked.dll", typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link.IFoo))]
+ [KeptMemberInAssembly ("copy.dll", typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy.A), "Method()")]
+ [KeptInterfaceOnTypeInAssembly ("copy.dll", typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy.A), "linked.dll", typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link.IFoo))]
+ public class InterfaceTypeInOtherUsedOnlyByCopiedAssembly {
+ public static void Main ()
+ {
+ InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy.ToKeepReferenceAtCompileTime ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit.cs
new file mode 100644
index 000000000..df3936a70
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ [SetupCompileBefore ("linked.dll", new [] {typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link)})]
+ [SetupCompileBefore ("copy.dll", new [] {typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy)}, new [] {"linked.dll"})]
+
+ [SetupLinkerAction ("copy", "copy")]
+ [SetupLinkerArgument ("-a", "copy")]
+
+ [KeptMemberInAssembly ("linked.dll", typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.IFoo), "Method()")]
+ [KeptMemberInAssembly ("copy.dll", typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy.A), "Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies.InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.IFoo.Method()")]
+ [KeptInterfaceOnTypeInAssembly ("copy.dll", typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy.A), "linked.dll", typeof (InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.IFoo))]
+ public class InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit {
+ public static void Main ()
+ {
+ InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy.ToKeepReferenceAtCompileTime ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeOnlyUsedHasInterfacesRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeOnlyUsedHasInterfacesRemoved.cs
new file mode 100644
index 000000000..2a444ac3d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceTypeOnlyUsedHasInterfacesRemoved.cs
@@ -0,0 +1,20 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class InterfaceTypeOnlyUsedHasInterfacesRemoved {
+ public static void Main ()
+ {
+ var tmp = typeof (IUsed).ToString ();
+ }
+
+ interface IRemovable1 {
+ }
+
+ interface IRemovable2 {
+ }
+
+ [Kept]
+ interface IUsed : IRemovable1, IRemovable2 {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceUsedOnlyAsConstraintIsKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceUsedOnlyAsConstraintIsKept.cs
new file mode 100644
index 000000000..b5fe34bd5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceUsedOnlyAsConstraintIsKept.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class InterfaceUsedOnlyAsConstraintIsKept {
+ public static void Main ()
+ {
+ var a = new A ();
+ Helper (a);
+ }
+
+ [Kept]
+ static void Helper<T> (T arg) where T : IFoo
+ {
+ }
+
+ [Kept]
+ interface IFoo {
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class A : IFoo {
+ public void Foo ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed.cs
new file mode 100644
index 000000000..5a7ff36f2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Inheritance.Interfaces.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ [SetupCompileBefore("library.dll", new []{"../Dependencies/InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.cs"})]
+ public class InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed {
+ public static void Main ()
+ {
+ Helper (null);
+ }
+
+ [Kept]
+ static void Helper (IBar obj)
+ {
+ var result = ((InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.IFoo) obj).ExplicitMethod ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof(InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.IFoo))]
+ interface IBar : InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.IFoo
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il
new file mode 100644
index 000000000..1d9ebade5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il
@@ -0,0 +1,68 @@
+.assembly extern mscorlib
+{
+}
+.assembly 'library'
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module 'library.dll'
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public auto ansi beforefieldinit Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib
+ extends [mscorlib]System.Object
+{
+ .class interface abstract auto ansi nested public IFoo
+ {
+ .method public hidebysig newslot abstract virtual
+ instance void Foo() cil managed
+ {
+ } // end of method IFoo::Foo
+
+ } // end of class IFoo
+
+ .class interface abstract auto ansi nested public IBar
+ {
+ .method public hidebysig newslot abstract virtual
+ instance void Bar() cil managed
+ {
+ } // end of method IBar::Bar
+
+ } // end of class IBar
+
+ .class auto ansi nested private beforefieldinit A
+ extends [mscorlib]System.Object
+ implements Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar,
+ Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IFoo
+ {
+ .method public hidebysig newslot virtual final
+ instance void Foo() cil managed
+ {
+ // Code size 1 (0x1)
+ .maxstack 8
+ IL_0000: ret
+ } // end of method A::Foo
+
+ .method public hidebysig newslot virtual final
+ instance void Bar() cil managed
+ {
+ // Code size 1 (0x1)
+ .maxstack 8
+ IL_0000: ret
+ } // end of method A::Bar
+
+ } // end of class A
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ }
+
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndAssemblyPreserveAll.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndAssemblyPreserveAll.cs
new file mode 100644
index 000000000..2b4dfd2e8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndAssemblyPreserveAll.cs
@@ -0,0 +1,27 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor
+{
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il" })]
+ [KeptInterfaceOnTypeInAssemblyAttribute ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IFoo")]
+ [KeptInterfaceOnTypeInAssemblyAttribute ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar")]
+ [KeptMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Foo()")]
+ [KeptMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Bar()")]
+ public class NoInstanceCtorAndAssemblyPreserveAll
+ {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndAssemblyPreserveAll.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndAssemblyPreserveAll.xml
new file mode 100644
index 000000000..82bd1ac97
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndAssemblyPreserveAll.xml
@@ -0,0 +1,3 @@
+<linker>
+ <assembly fullname="library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" preserve="all"/>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveAll.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveAll.cs
new file mode 100644
index 000000000..32bbe139f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveAll.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor {
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il" })]
+ [KeptInterfaceOnTypeInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IFoo")]
+ [KeptInterfaceOnTypeInAssemblyAttribute ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar")]
+ [KeptMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Foo()")]
+ [KeptMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Bar()")]
+ public class NoInstanceCtorAndTypePreserveAll {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveAll.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveAll.xml
new file mode 100644
index 000000000..b6a27cfed
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveAll.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A" preserve="all"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.cs
new file mode 100644
index 000000000..22b2bed90
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor {
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il" })]
+
+ // The interfaces should be removed because the interface types are not marked
+ [RemovedInterfaceOnTypeInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IFoo")]
+ [RemovedInterfaceOnTypeInAssemblyAttribute ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar")]
+
+ [RemovedMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Foo()")]
+ [RemovedMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Bar()")]
+
+ // pedump reports this is valid with the following error.
+ //
+ // Assertion at metadata.c:1073, condition `index < meta->heap_blob.size' not met
+ //
+ // Not worried about it since this is already a niche edge case. Let's just skip verify for pedump
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ public class NoInstanceCtorAndTypePreserveFields {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.xml
new file mode 100644
index 000000000..94b681a9d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFields.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A" preserve="fields"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs
new file mode 100644
index 000000000..6bcaaa651
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs
@@ -0,0 +1,41 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor {
+ [Define("IL_ASSEMBLY_COMPILED")]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il" })]
+
+ // Interfaces should be removed because preserve fields would not normally cause an instance ctor to be marked. This means that no instance ctor
+ // sweeping logic should kick in and remove interfaces
+ [RemovedInterfaceOnTypeInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IFoo")]
+ [RemovedInterfaceOnTypeInAssemblyAttribute ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar")]
+
+ // Methods are removed because we only preserved fields
+ [RemovedMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Foo()")]
+ [RemovedMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Bar()")]
+
+ // pedump reports this is valid with the following error.
+ //
+ // Assertion at metadata.c:1073, condition `index < meta->heap_blob.size' not met
+ //
+ // Not worried about it since this is already a niche edge case. Let's just skip verify for pedump
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ public class NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked {
+ public static void Main ()
+ {
+#if IL_ASSEMBLY_COMPILED
+ var tmp = typeof (Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib.IFoo).ToString ();
+#endif
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.xml
new file mode 100644
index 000000000..674b3ca86
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A" preserve="fields"/>
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar" preserve="none"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethods.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethods.cs
new file mode 100644
index 000000000..045aa2dcb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethods.cs
@@ -0,0 +1,29 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor {
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il" })]
+
+ // The interfaces should be removed because the interface types are not marked
+ [RemovedInterfaceOnTypeInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IFoo")]
+ [RemovedInterfaceOnTypeInAssemblyAttribute ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar")]
+
+ // Methods should be kept because of the preserve methods
+ [KeptMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Foo()")]
+ [KeptMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Bar()")]
+ public class NoInstanceCtorAndTypePreserveMethods {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethods.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethods.xml
new file mode 100644
index 000000000..00a06f0c9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethods.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A" preserve="methods"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.cs
new file mode 100644
index 000000000..419eae41c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor {
+ [Define("IL_ASSEMBLY_COMPILED")]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il" })]
+
+ // Interfaces will be removed because there is no instance ctor that is marked.
+ [RemovedInterfaceOnTypeInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IFoo")]
+ [RemovedInterfaceOnTypeInAssemblyAttribute ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar")]
+
+ // Methods should be kept because of the preserve methods
+ [KeptMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Foo()")]
+ [KeptMemberInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "Bar()")]
+ public class NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked
+ {
+ public static void Main()
+ {
+ // We'll mark one interface in code and one via xml, the end result should be the same
+#if IL_ASSEMBLY_COMPILED
+ var tmp = typeof (Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib.IFoo).ToString ();
+#endif
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.xml
new file mode 100644
index 000000000..95d6579de
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A" preserve="methods"/>
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar" preserve="none"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.cs
new file mode 100644
index 000000000..670d45e43
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor {
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/NoInstanceCtorAndAssemblyPreserveAll_Lib.il" })]
+ [RemovedInterfaceOnTypeInAssembly ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IFoo")]
+ [RemovedInterfaceOnTypeInAssemblyAttribute ("library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A",
+ "library",
+ "Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/IBar")]
+ // pedump reports this is valid with the following error.
+ //
+ // Assertion at metadata.c:1073, condition `index < meta->heap_blob.size' not met
+ //
+ // Not worried about it since this is already a niche edge case. Let's just skip verify for pedump
+ [SkipPeVerify (SkipPeVerifyForToolchian.Pedump)]
+ public class NoInstanceCtorAndTypePreserveNone {
+ public static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.xml
new file mode 100644
index 000000000..079694287
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoInstanceCtor/NoInstanceCtorAndTypePreserveNone.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoInstanceCtor.Dependencies.NoInstanceCtorAndAssemblyPreserveAll_Lib/A" preserve="none"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ComInterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ComInterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs
new file mode 100644
index 000000000..62da67caf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ComInterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs
@@ -0,0 +1,29 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class ComInterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod {
+ public static void Main ()
+ {
+ StaticMethodOnlyUsed.StaticMethod ();
+ }
+
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ interface IUnusedInterface {
+ void Foo ();
+ }
+
+ [Kept]
+ class StaticMethodOnlyUsed : IUnusedInterface {
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ExplicitInterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ExplicitInterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs
new file mode 100644
index 000000000..f3bb78c8f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ExplicitInterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs
@@ -0,0 +1,40 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class ExplicitInterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed {
+ public static void Main ()
+ {
+ IUsedInterface p = new UsedClass ();
+ StaticMethodOnlyUsed.StaticMethod ();
+ p.Foo ();
+ }
+
+ [Kept]
+ interface IUsedInterface {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IUsedInterface))]
+ class UsedClass : IUsedInterface {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ class StaticMethodOnlyUsed : IUsedInterface {
+ void IUsedInterface.Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/GenericType.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/GenericType.cs
new file mode 100644
index 000000000..b6dff2fde
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/GenericType.cs
@@ -0,0 +1,22 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class GenericType {
+ public static void Main ()
+ {
+ object o = new Bar<Foo> ();
+ }
+
+ [Kept]
+ [KeptMember(".ctor()")]
+ class Bar<T> {
+ }
+
+ [Kept]
+ class Foo : IFoo {
+ }
+
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/GenericWithConstraintDoesNotCauseOtherTypesToKeepInterface.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/GenericWithConstraintDoesNotCauseOtherTypesToKeepInterface.cs
new file mode 100644
index 000000000..7255cac2c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/GenericWithConstraintDoesNotCauseOtherTypesToKeepInterface.cs
@@ -0,0 +1,41 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class GenericWithConstraintDoesNotCauseOtherTypesToKeepInterface {
+ public static void Main ()
+ {
+ Foo f = null;
+ Helper (f);
+ OtherMethodToDoStuff ();
+ }
+
+ [Kept]
+ static void Helper<T> (T f) where T : IFoo
+ {
+ }
+
+ [Kept]
+ static void OtherMethodToDoStuff ()
+ {
+ HelperToUseFoo2 (null);
+ }
+
+ [Kept]
+ static void HelperToUseFoo2 (Foo2 f)
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ class Foo2 : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs
new file mode 100644
index 000000000..bddacb9d5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs
@@ -0,0 +1,40 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed {
+ public static void Main ()
+ {
+ IUsedInterface p = new UsedClass ();
+ StaticMethodOnlyUsed.StaticMethod ();
+ p.Foo ();
+ }
+
+ [Kept]
+ interface IUsedInterface {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IUsedInterface))]
+ class UsedClass : IUsedInterface {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ class StaticMethodOnlyUsed : IUsedInterface {
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs
new file mode 100644
index 000000000..9d79e5e0b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs
@@ -0,0 +1,51 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor {
+ public static void Main ()
+ {
+ IUsedInterface p = new UsedClass ();
+ StaticMethodOnlyUsed.StaticMethod ();
+ p.Foo ();
+ }
+
+ [Kept]
+ interface IUsedInterface {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IUsedInterface))]
+ class UsedClass : IUsedInterface {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ class StaticMethodOnlyUsed : IUsedInterface {
+ [Kept]
+ static StaticMethodOnlyUsed ()
+ {
+ UsedByStaticCctor ();
+ }
+
+ [Kept]
+ static void UsedByStaticCctor ()
+ {
+ }
+
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceFromCopiedAssemblyCanBeRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceFromCopiedAssemblyCanBeRemoved.cs
new file mode 100644
index 000000000..b8001883e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceFromCopiedAssemblyCanBeRemoved.cs
@@ -0,0 +1,24 @@
+using System.Collections;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class InterfaceFromCopiedAssemblyCanBeRemoved {
+ public static void Main ()
+ {
+ Foo.StaticMethod ();
+ }
+
+ [Kept]
+ class Foo : IComparer {
+ public int Compare (object x, object y)
+ {
+ throw new System.NotImplementedException ();
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs
new file mode 100644
index 000000000..828376342
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod {
+ public static void Main ()
+ {
+ StaticMethodOnlyUsed.StaticMethod ();
+ }
+
+ interface IUnusedInterface {
+ void Foo ();
+ }
+
+ [Kept]
+ class StaticMethodOnlyUsed : IUnusedInterface {
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs
new file mode 100644
index 000000000..fea5b9954
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs
@@ -0,0 +1,53 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple {
+ public static void Main ()
+ {
+ IUsedInterface p = new UsedClass ();
+ StaticMethodOnlyUsed.StaticMethod ();
+ p.Foo ();
+
+ // We are testing removing interfaces when no instance is created, we need to mark the interface types
+ // so that we don't end up testing unused interface types being swept
+ var tmp = typeof (IRemovable1).ToString ();
+ tmp = typeof (IRemovable2).ToString ();
+ }
+
+ [Kept]
+ interface IUsedInterface {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ interface IRemovable1 {
+ }
+
+ [Kept]
+ interface IRemovable2 {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IUsedInterface))]
+ class UsedClass : IUsedInterface {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ class StaticMethodOnlyUsed : IUsedInterface, IRemovable1, IRemovable2 {
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/LocalDowncastDoesNotCuaseOtherTypesToKeepInterface.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/LocalDowncastDoesNotCuaseOtherTypesToKeepInterface.cs
new file mode 100644
index 000000000..00ad89fd2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/LocalDowncastDoesNotCuaseOtherTypesToKeepInterface.cs
@@ -0,0 +1,47 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class LocalDowncastDoesNotCuaseOtherTypesToKeepInterface {
+ public static void Main ()
+ {
+ Foo f = null;
+ IFoo i = f;
+ i.Method ();
+ DoOtherStuff ();
+ }
+
+ [Kept]
+ static void DoOtherStuff ()
+ {
+ HelperToUseBar (null);
+ }
+
+ [Kept]
+ static void HelperToUseBar (Bar arg)
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ [Kept] // TODO : It should be safe to stub this. It can't actually be called because no instance of Foo ever exists
+ public void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Method ();
+ }
+
+ [Kept]
+ class Bar : IFoo
+ {
+ public void Method ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ObjectHardCastedToInterface.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ObjectHardCastedToInterface.cs
new file mode 100644
index 000000000..84b9b6c16
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/ObjectHardCastedToInterface.cs
@@ -0,0 +1,40 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class ObjectHardCastedToInterface {
+ public static void Main ()
+ {
+ object o = GetAnObject ();
+ IFoo i = (IFoo)o;
+ UseAnIFoo (i);
+
+ // Here to mark Foo so that we can verify the interface is removed
+ Foo.Helper ();
+ }
+
+ [Kept]
+ static object GetAnObject ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static void UseAnIFoo (IFoo arg)
+ {
+ }
+
+ [Kept]
+ class Foo : IFoo
+ {
+ [Kept]
+ public static void Helper ()
+ {
+ }
+ }
+
+ [Kept]
+ interface IFoo
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/PreserveDependencyPreservesInterfaceMethod.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/PreserveDependencyPreservesInterfaceMethod.cs
new file mode 100644
index 000000000..a9b0bc1d6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/PreserveDependencyPreservesInterfaceMethod.cs
@@ -0,0 +1,32 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ /// <summary>
+ /// The interface can still be removed in this case because PreserveDependency is just preserving Foo() on the current type
+ /// </summary>
+ public class PreserveDependencyPreservesInterfaceMethod {
+ public static void Main ()
+ {
+ StaticMethodOnlyUsed.StaticMethod ();
+ }
+
+ interface IUnusedInterface {
+ void Foo ();
+ }
+
+ [Kept]
+ class StaticMethodOnlyUsed : IUnusedInterface {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ [PreserveDependency ("Foo")]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.cs
new file mode 100644
index 000000000..fef505898
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.cs
@@ -0,0 +1,34 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class UnusedTypeHasExplicitInterfaceMethodPreservedViaXml {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class A : IBar, IFoo {
+
+ // Because an explicit interface method was preserved via xml, we need to now mark the interface implementation
+ [Kept]
+ void IFoo.Foo ()
+ {
+ }
+
+ void IBar.Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.xml
new file mode 100644
index 000000000..608579eab
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.xml
@@ -0,0 +1,7 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeHasExplicitInterfaceMethodPreservedViaXml/A">
+ <method signature="System.Void Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.IFoo.Foo()"/>
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.cs
new file mode 100644
index 000000000..191928690
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.cs
@@ -0,0 +1,29 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class UnusedTypeHasExplicitInterfacePropertyPreservedViaXml {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ int Foo { [Kept] get; [Kept] set; }
+ }
+
+ interface IBar {
+ int Bar { get; set; }
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class A : IBar, IFoo {
+ [Kept]
+ [KeptBackingField]
+ int IFoo.Foo { [Kept] get; [Kept] set; }
+
+ int IBar.Bar { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.xml
new file mode 100644
index 000000000..f821a3d88
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.xml
@@ -0,0 +1,7 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeHasExplicitInterfacePropertyPreservedViaXml/A">
+ <property signature="System.Int32 Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.IFoo.Foo"/>
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasInterfaceMethodPreservedViaXml.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasInterfaceMethodPreservedViaXml.cs
new file mode 100644
index 000000000..eef586956
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasInterfaceMethodPreservedViaXml.cs
@@ -0,0 +1,29 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class UnusedTypeHasInterfaceMethodPreservedViaXml {
+ public static void Main ()
+ {
+ }
+
+ interface IFoo {
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ class A : IBar, IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasInterfaceMethodPreservedViaXml.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasInterfaceMethodPreservedViaXml.xml
new file mode 100644
index 000000000..2abd15c89
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeHasInterfaceMethodPreservedViaXml.xml
@@ -0,0 +1,7 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeHasInterfaceMethodPreservedViaXml/A">
+ <method signature="System.Void Foo()"/>
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveFields.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveFields.cs
new file mode 100644
index 000000000..7c7b3b49a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveFields.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class UnusedTypeWithPreserveFields {
+ public static void Main ()
+ {
+ }
+
+ interface IFoo {
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ class A : IBar, IFoo {
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveFields.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveFields.xml
new file mode 100644
index 000000000..9106c06bd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveFields.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeWithPreserveFields/A" preserve="fields"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethods.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethods.cs
new file mode 100644
index 000000000..d729f60df
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethods.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class UnusedTypeWithPreserveMethods {
+ public static void Main ()
+ {
+ }
+
+ interface IFoo {
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class A : IBar, IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethods.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethods.xml
new file mode 100644
index 000000000..f75f875b7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethods.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeWithPreserveMethods/A" preserve="methods"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.cs
new file mode 100644
index 000000000..183bac795
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.cs
@@ -0,0 +1,37 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor {
+ public class UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked {
+ public static void Main ()
+ {
+ // We'll mark one interface in code and one via xml, the end result should be the same
+ var tmp = typeof (IFoo).ToString ();
+ }
+
+ [Kept]
+ interface IFoo {
+ void Foo ();
+ }
+
+ [Kept]
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ [KeptInterface (typeof (IBar))]
+ class A : IBar, IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.xml
new file mode 100644
index 000000000..7a61853c9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtor/UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked/A" preserve="methods"/>
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtor.UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked/IBar" preserve="none"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ArrayPassedAsParameter.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ArrayPassedAsParameter.cs
new file mode 100644
index 000000000..0a9aacc0c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ArrayPassedAsParameter.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class LocalArrayPassedAsParameter {
+ public static void Main ()
+ {
+ Foo [] arr = null;
+ Helper (arr);
+ }
+
+ [Kept]
+ static void Helper (IFoo[] f)
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ArrayWithIndexAssignedToReturnValue.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ArrayWithIndexAssignedToReturnValue.cs
new file mode 100644
index 000000000..179b7577b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ArrayWithIndexAssignedToReturnValue.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class ArrayWithIndexAssignedToReturnValue {
+ public static void Main ()
+ {
+ IFoo [] arr = new IFoo [5];
+ arr [0] = GetAFoo ();
+ }
+
+ [Kept]
+ static Foo GetAFoo ()
+ {
+ return null;
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/FieldDowncastedToInterface.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/FieldDowncastedToInterface.cs
new file mode 100644
index 000000000..84ff1a1c7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/FieldDowncastedToInterface.cs
@@ -0,0 +1,32 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class FieldDowncastedToInterface {
+ [Kept]
+ private static Foo f;
+ [Kept]
+ private static IFoo i;
+
+ public static void Main ()
+ {
+ f = null;
+ i = f;
+ i.Method ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ [Kept] // TODO : It should be safe to stub this. It can't actually be called because no instance of Foo ever exists
+ public void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Method ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericType.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericType.cs
new file mode 100644
index 000000000..7e8e8ffa9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericType.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class GenericType {
+ public static void Main ()
+ {
+ Foo f = null;
+ Bar<IFoo> o = new Bar<IFoo> ();
+ o.Method (f);
+ }
+
+ [Kept]
+ [KeptMember(".ctor()")]
+ class Bar<T> {
+ [Kept]
+ public void Method (T arg)
+ {
+ }
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint.cs
new file mode 100644
index 000000000..48051732a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class GenericTypeWithConstraint {
+ public static void Main ()
+ {
+ object o = new Bar<Foo> ();
+ }
+
+ [Kept]
+ [KeptMember(".ctor()")]
+ class Bar<T> where T : IFoo {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint2.cs
new file mode 100644
index 000000000..0fb889ae8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint2.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class GenericTypeWithConstraint2 {
+ public static void Main ()
+ {
+ Foo f = null;
+ Bar<Foo>.Helper (f);
+ }
+
+ [Kept]
+ static class Bar<T> where T : IFoo {
+ [Kept]
+ public static void Helper (T arg)
+ {
+ }
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint3.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint3.cs
new file mode 100644
index 000000000..bc170287e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/GenericTypeWithConstraint3.cs
@@ -0,0 +1,58 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class GenericTypeWithConstraint3 {
+ public static void Main ()
+ {
+ Foo f = null;
+ Bar b = null;
+ Bar<BaseFoo2, BaseBar2>.Helper (f, b);
+ }
+
+ [Kept]
+ static class Bar<T, K> where T : IFoo where K : IBar {
+ [Kept]
+ public static void Helper (T arg, K arg2)
+ {
+ }
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ abstract class BaseFoo : IFoo {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (BaseFoo))]
+ abstract class BaseFoo2 : BaseFoo {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IBar))]
+ abstract class BaseBar : IBar {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (BaseBar))]
+ abstract class BaseBar2 : BaseBar {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (BaseFoo2))]
+ class Foo : BaseFoo2 {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (BaseBar2))]
+ class Bar : BaseBar2 {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+
+ [Kept]
+ interface IBar {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/InterfaceOnMultipleBases.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/InterfaceOnMultipleBases.cs
new file mode 100644
index 000000000..6b303e24f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/InterfaceOnMultipleBases.cs
@@ -0,0 +1,42 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class InterfaceOnMultipleBases {
+ public static void Main ()
+ {
+ Foo f = null;
+ Helper (f);
+ }
+
+ [Kept]
+ static void Helper (IFoo f)
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Base : IFoo {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base))]
+ [KeptInterface (typeof (IFoo))]
+ class Base2 : Base, IFoo {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base2))]
+ class Base3 : Base2 {
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (Base3))]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : Base3, IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalDowncastedToInterface.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalDowncastedToInterface.cs
new file mode 100644
index 000000000..dc63d99a3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalDowncastedToInterface.cs
@@ -0,0 +1,27 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class LocalDowncastedToInterface {
+ public static void Main ()
+ {
+ Foo f = null;
+ IFoo i = f;
+ i.Method ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ [Kept] // TODO : It should be safe to stub this. It can't actually be called because no instance of Foo ever exists
+ public void Method ()
+ {
+ }
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Method ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameter.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameter.cs
new file mode 100644
index 000000000..5338cc6ba
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameter.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class LocalPassedAsParameter {
+ public static void Main ()
+ {
+ Foo f = null;
+ Helper (f);
+ }
+
+ [Kept]
+ static void Helper (IFoo f)
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGeneric.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGeneric.cs
new file mode 100644
index 000000000..475ac098a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGeneric.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class LocalPassedAsParameterToGeneric {
+ public static void Main ()
+ {
+ Foo f = null;
+ Helper<IFoo>(f);
+ }
+
+ [Kept]
+ static void Helper <T> (T f)
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGenericWithConstraint.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGenericWithConstraint.cs
new file mode 100644
index 000000000..e00229264
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGenericWithConstraint.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class LocalPassedAsParameterToGenericWithConstraint {
+ public static void Main ()
+ {
+ Foo f = null;
+ Helper (f);
+ }
+
+ [Kept]
+ static void Helper<T> (T f) where T : IFoo
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGenericWithConstraint2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGenericWithConstraint2.cs
new file mode 100644
index 000000000..cecf742e4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/LocalPassedAsParameterToGenericWithConstraint2.cs
@@ -0,0 +1,32 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class LocalPassedAsParameterToGenericWithConstraint2 {
+ public static void Main ()
+ {
+ Foo f = null;
+ Foo2 f2 = null;
+ Helper (f, f2);
+ }
+
+ [Kept]
+ static void Helper<T> (T f, Foo2 arg2) where T : IFoo
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))] // technically this can be removed, but it would require more complex knowledge of the stack to do so
+ class Foo2 : IFoo {
+ }
+
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ReturnValueDowncastedToInterface.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ReturnValueDowncastedToInterface.cs
new file mode 100644
index 000000000..0aef967a5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/NoKeptCtorButInterfaceNeeded/ReturnValueDowncastedToInterface.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.NoKeptCtorButInterfaceNeeded {
+ public class ReturnValueDowncastedToInterface {
+ public static void Main ()
+ {
+ UseAnIFoo (GetAFoo ());
+ }
+
+ [Kept]
+ static Foo GetAFoo ()
+ {
+ return null;
+ }
+
+ [Kept]
+ static void UseAnIFoo (IFoo arg)
+ {
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ class Foo : IFoo {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ObjectCastedToSecondInterfaceHasMemberRemovedButInterfaceKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ObjectCastedToSecondInterfaceHasMemberRemovedButInterfaceKept.cs
new file mode 100644
index 000000000..95fd8b266
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/ObjectCastedToSecondInterfaceHasMemberRemovedButInterfaceKept.cs
@@ -0,0 +1,38 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class ObjectCastedToSecondInterfaceHasMemberRemovedButInterfaceKept {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ var b = (IBar) i;
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ [KeptInterface (typeof (IBar))]
+ class A : IBar, IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/TypeGetsMarkedThatImplementsAlreadyMarkedInterfaceMethod.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/TypeGetsMarkedThatImplementsAlreadyMarkedInterfaceMethod.cs
new file mode 100644
index 000000000..85f1c855a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/TypeGetsMarkedThatImplementsAlreadyMarkedInterfaceMethod.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ class TypeGetsMarkedThatImplementsAlreadyMarkedInterfaceMethod {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class B : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class A : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ new B (); /*this will cause us to mark B, but will we be smart enough to realize B.Foo implements the already marked IFoo.Foo?*/
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsKept.cs
new file mode 100644
index 000000000..4e7212bef
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsKept.cs
@@ -0,0 +1,38 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ /// <summary>
+ /// It's much harder to know if a com interface will be needed since so much can be on the native side.
+ /// As a precaution we will not apply the unused interface rules to com interfaces
+ /// </summary>
+ public class UnusedComInterfaceIsKept {
+ public static void Main ()
+ {
+ var i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IBar))]
+ class A : IBar {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsRemovedWhenComFeatureExcluded.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsRemovedWhenComFeatureExcluded.cs
new file mode 100644
index 000000000..de8908678
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedComInterfaceIsRemovedWhenComFeatureExcluded.cs
@@ -0,0 +1,33 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ [SetupLinkerArgument ("--exclude-feature", "com")]
+ public class UnusedComInterfaceIsRemovedWhenComFeatureExcluded {
+ public static void Main ()
+ {
+ var i = new A ();
+ i.Foo ();
+ }
+
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class A : IBar {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceHasMethodPreservedViaXml.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceHasMethodPreservedViaXml.cs
new file mode 100644
index 000000000..1a97b7836
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceHasMethodPreservedViaXml.cs
@@ -0,0 +1,39 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class UnusedExplicitInterfaceHasMethodPreservedViaXml {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ interface IBar {
+ [Kept]
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ [KeptInterface (typeof (IBar))]
+ class A : IBar, IFoo {
+ [Kept]
+ void IFoo.Foo ()
+ {
+ }
+
+ [Kept]
+ void IBar.Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceHasMethodPreservedViaXml.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceHasMethodPreservedViaXml.xml
new file mode 100644
index 000000000..8a6a8d28e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceHasMethodPreservedViaXml.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.UnusedExplicitInterfaceHasMethodPreservedViaXml/A" preserve="methods"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceIsRemoved.cs
new file mode 100644
index 000000000..7afcd6056
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedExplicitInterfaceIsRemoved.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class UnusedExplicitInterfaceIsRemoved {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class A : IBar, IFoo {
+ [Kept]
+ void IFoo.Foo ()
+ {
+ }
+
+ void IBar.Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceHasMethodPreservedViaXml.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceHasMethodPreservedViaXml.cs
new file mode 100644
index 000000000..2b5e7ea2f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceHasMethodPreservedViaXml.cs
@@ -0,0 +1,36 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class UnusedInterfaceHasMethodPreservedViaXml {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class A : IBar, IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceHasMethodPreservedViaXml.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceHasMethodPreservedViaXml.xml
new file mode 100644
index 000000000..0db48c0df
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceHasMethodPreservedViaXml.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType.UnusedInterfaceHasMethodPreservedViaXml/A" preserve="methods"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceTypeIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceTypeIsRemoved.cs
new file mode 100644
index 000000000..69e55bead
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnReferenceType/UnusedInterfaceTypeIsRemoved.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnReferenceType {
+ public class UnusedInterfaceTypeIsRemoved {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class A : IBar, IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs
new file mode 100644
index 000000000..260dcb92e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs
@@ -0,0 +1,42 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType.NoKeptCtor {
+ public class InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed {
+ public static void Main ()
+ {
+ IUsedInterface p = new UsedClass ();
+ StaticMethodOnlyUsed.StaticMethod ();
+ p.Foo ();
+ }
+
+ [Kept]
+ interface IUsedInterface {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IUsedInterface))]
+ class UsedClass : IUsedInterface {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IUsedInterface))] // Could be removed in the future with improved handling of value types
+ struct StaticMethodOnlyUsed : IUsedInterface {
+ [Kept] // Could be removed in the future with improved handling of value types
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs
new file mode 100644
index 000000000..0ce19620b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs
@@ -0,0 +1,53 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType.NoKeptCtor {
+ public class InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor {
+ public static void Main ()
+ {
+ IUsedInterface p = new UsedClass ();
+ StaticMethodOnlyUsed.StaticMethod ();
+ p.Foo ();
+ }
+
+ [Kept]
+ interface IUsedInterface {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IUsedInterface))]
+ class UsedClass : IUsedInterface {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IUsedInterface))] // Could be removed in the future with improved handling of value types
+ struct StaticMethodOnlyUsed : IUsedInterface {
+ [Kept]
+ static StaticMethodOnlyUsed ()
+ {
+ UsedByStaticCctor ();
+ }
+
+ [Kept]
+ static void UsedByStaticCctor ()
+ {
+ }
+
+ [Kept] // Could be removed in the future with improved handling of value types
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs
new file mode 100644
index 000000000..54680898a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs
@@ -0,0 +1,32 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType.NoKeptCtor {
+ public class InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod {
+ public static void Main ()
+ {
+ StaticMethodOnlyUsed.StaticMethod ();
+
+ // We are testing removing interfaces when no instance is created, we need to mark the interface types
+ // so that we don't end up testing unused interface types being swept
+ var tmp = typeof (IUsedInterface).ToString ();
+ }
+
+ [Kept] // Could be removed in the future with improved handling of value types
+ interface IUsedInterface {
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IUsedInterface))] // Could be removed in the future with improved handling of value types
+ struct StaticMethodOnlyUsed : IUsedInterface {
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs
new file mode 100644
index 000000000..a6eadcabf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/NoKeptCtor/InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs
@@ -0,0 +1,57 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType.NoKeptCtor {
+ public class InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple {
+ public static void Main ()
+ {
+ IUsedInterface p = new UsedClass ();
+ StaticMethodOnlyUsed.StaticMethod ();
+ p.Foo ();
+
+ // We are testing removing interfaces when no instance is created, we need to mark the interface types
+ // so that we don't end up testing unused interface types being swept
+ var tmp = typeof (IRemovable1).ToString ();
+ tmp = typeof (IRemovable2).ToString ();
+ }
+
+ [Kept]
+ interface IUsedInterface {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept] // Could be removed in the future with improved handling of value types
+ interface IRemovable1 {
+ }
+
+ [Kept] // Could be removed in the future with improved handling of value types
+ interface IRemovable2 {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IUsedInterface))]
+ class UsedClass : IUsedInterface {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IUsedInterface))] // Could be removed in the future with improved handling of value types
+ [KeptInterface (typeof (IRemovable1))] // Could be removed in the future with improved handling of value types
+ [KeptInterface (typeof (IRemovable2))] // Could be removed in the future with improved handling of value types
+ struct StaticMethodOnlyUsed : IUsedInterface, IRemovable1, IRemovable2 {
+ [Kept] // Could be removed in the future with improved handling of value types
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public static void StaticMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructImplementingInterfaceMethodsNested.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructImplementingInterfaceMethodsNested.cs
new file mode 100644
index 000000000..1108175bf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructImplementingInterfaceMethodsNested.cs
@@ -0,0 +1,34 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType {
+ public class StructImplementingInterfaceMethodsNested {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar : IFoo {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ struct A : IBar {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructImplementingInterfaceMethodsNested2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructImplementingInterfaceMethodsNested2.cs
new file mode 100644
index 000000000..f7a701dc1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructImplementingInterfaceMethodsNested2.cs
@@ -0,0 +1,38 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType {
+ public class StructImplementingInterfaceMethodsNested2 {
+ public static void Main ()
+ {
+ IBar b = new A ();
+ IFoo f = b;
+ f.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ interface IBar : IFoo {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IBar))]
+ [KeptInterface (typeof (IFoo))]
+ struct A : IBar {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromConcreteTypeHasInterfaceMethodRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromConcreteTypeHasInterfaceMethodRemoved.cs
new file mode 100644
index 000000000..a1996be28
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromConcreteTypeHasInterfaceMethodRemoved.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType
+{
+ class StructUsedFromConcreteTypeHasInterfaceMethodRemoved {
+ public static void Main ()
+ {
+ A a = new A ();
+ a.Foo ();
+ }
+
+ [Kept]
+ struct A : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ public interface IFoo {
+ void Foo ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs
new file mode 100644
index 000000000..246f682a8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType {
+ public class StructUsedFromConcreteTypeHasInterfaceMethodRemoved2 {
+ public static void Main ()
+ {
+ A a = new A ();
+ a.Foo ();
+
+ // If IFoo is marked for any reason then all of a sudden we do need to keep IFoo on A
+ var tmp = typeof (IFoo).ToString ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ struct A : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ public interface IFoo {
+ void Foo ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromInterfaceHasInterfaceMethodKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromInterfaceHasInterfaceMethodKept.cs
new file mode 100644
index 000000000..83935642d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/StructUsedFromInterfaceHasInterfaceMethodKept.cs
@@ -0,0 +1,27 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType
+{
+ class StructUsedFromInterfaceHasInterfaceMethodKept {
+ public static void Main ()
+ {
+ IFoo a = new A ();
+ a.Foo ();
+ }
+
+ [Kept]
+ [KeptInterface (typeof (IFoo))]
+ struct A : IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+ }
+
+ [Kept]
+ public interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceHasMethodPreservedViaXml.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceHasMethodPreservedViaXml.cs
new file mode 100644
index 000000000..4e76aa1a5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceHasMethodPreservedViaXml.cs
@@ -0,0 +1,39 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType {
+ public class UnusedExplicitInterfaceHasMethodPreservedViaXml {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ [Kept]
+ interface IBar {
+ [Kept]
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ [KeptInterface (typeof (IBar))]
+ struct A : IBar, IFoo {
+ [Kept]
+ void IFoo.Foo ()
+ {
+ }
+
+ [Kept]
+ void IBar.Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceHasMethodPreservedViaXml.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceHasMethodPreservedViaXml.xml
new file mode 100644
index 000000000..988ac904d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceHasMethodPreservedViaXml.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType.UnusedExplicitInterfaceHasMethodPreservedViaXml/A" preserve="methods"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceIsRemoved.cs
new file mode 100644
index 000000000..f731e3bdc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedExplicitInterfaceIsRemoved.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType {
+ public class UnusedExplicitInterfaceIsRemoved {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ struct A : IBar, IFoo {
+ [Kept]
+ void IFoo.Foo ()
+ {
+ }
+
+ void IBar.Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceHasMethodPreservedViaXml.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceHasMethodPreservedViaXml.cs
new file mode 100644
index 000000000..89cf4d264
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceHasMethodPreservedViaXml.cs
@@ -0,0 +1,36 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType {
+ public class UnusedInterfaceHasMethodPreservedViaXml {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ struct A : IBar, IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ [Kept]
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceHasMethodPreservedViaXml.xml b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceHasMethodPreservedViaXml.xml
new file mode 100644
index 000000000..1788f88b8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceHasMethodPreservedViaXml.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType.UnusedInterfaceHasMethodPreservedViaXml/A" preserve="methods"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceTypeIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceTypeIsRemoved.cs
new file mode 100644
index 000000000..82ececac1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.Interfaces/OnValueType/UnusedInterfaceTypeIsRemoved.cs
@@ -0,0 +1,35 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.Interfaces.OnValueType {
+ public class UnusedInterfaceTypeIsRemoved {
+ public static void Main ()
+ {
+ IFoo i = new A ();
+ i.Foo ();
+ }
+
+ [Kept]
+ interface IFoo {
+ [Kept]
+ void Foo ();
+ }
+
+ interface IBar {
+ void Bar ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ struct A : IBar, IFoo {
+ [Kept]
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/HarderToDetectUnusedVirtualMethodGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/HarderToDetectUnusedVirtualMethodGetsRemoved.cs
new file mode 100644
index 000000000..8348dbd09
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/HarderToDetectUnusedVirtualMethodGetsRemoved.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.VirtualMethods {
+ class HarderToDetectUnusedVirtualMethodGetsRemoved {
+ public static void Main ()
+ {
+ new Base ().Call ();
+ }
+
+ static void DeadCode ()
+ {
+ new B ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Base {
+ [Kept]
+ public virtual void Call ()
+ {
+ }
+ }
+
+ class B : Base {
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UnusedTypeWithOverrideOfVirtualMethodIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UnusedTypeWithOverrideOfVirtualMethodIsRemoved.cs
new file mode 100644
index 000000000..57e84bca1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UnusedTypeWithOverrideOfVirtualMethodIsRemoved.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.VirtualMethods {
+ class UnusedTypeWithOverrideOfVirtualMethodIsRemoved {
+ public static void Main ()
+ {
+ new Base ().Call ();
+ }
+
+ [KeptMember (".ctor()")]
+ class Base {
+ [Kept]
+ public virtual void Call ()
+ {
+ }
+ }
+
+ class B : Base {
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UnusedVirtualMethodRemoved.cs b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UnusedVirtualMethodRemoved.cs
new file mode 100644
index 000000000..88bd1f8ec
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UnusedVirtualMethodRemoved.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.VirtualMethods {
+ public class UnusedVirtualMethodRemoved {
+ public static void Main ()
+ {
+ var tmp = new B ();
+ }
+
+ [KeptMember (".ctor()")]
+ class Base {
+ public virtual void Call ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ class B : Base {
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UsedOverrideOfVirtualMethodIsKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UsedOverrideOfVirtualMethodIsKept.cs
new file mode 100644
index 000000000..27b3c90dd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UsedOverrideOfVirtualMethodIsKept.cs
@@ -0,0 +1,29 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.VirtualMethods {
+ public class UsedOverrideOfVirtualMethodIsKept {
+ public static void Main ()
+ {
+ var tmp = new B ();
+ tmp.Call ();
+ }
+
+ [KeptMember (".ctor()")]
+ class Base {
+ [Kept]
+ public virtual void Call ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ class B : Base {
+ [Kept]
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UsedTypeWithOverrideOfVirtualMethodHasOverrideKept.cs b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UsedTypeWithOverrideOfVirtualMethodHasOverrideKept.cs
new file mode 100644
index 000000000..2474d8dfa
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/UsedTypeWithOverrideOfVirtualMethodHasOverrideKept.cs
@@ -0,0 +1,29 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.VirtualMethods {
+ public class UsedTypeWithOverrideOfVirtualMethodHasOverrideKept {
+ public static void Main ()
+ {
+ new B ();
+ new Base ().Call ();
+ }
+
+ [KeptMember (".ctor()")]
+ class Base {
+ [Kept]
+ public virtual void Call ()
+ {
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (Base))]
+ class B : Base {
+ [Kept]
+ public override void Call ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/VirtualMethodGetsPerservedIfBaseMethodGetsInvoked.cs b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/VirtualMethodGetsPerservedIfBaseMethodGetsInvoked.cs
new file mode 100644
index 000000000..0b1d75d75
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/VirtualMethodGetsPerservedIfBaseMethodGetsInvoked.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.VirtualMethods {
+ class VirtualMethodGetsPerservedIfBaseMethodGetsInvoked {
+ public static void Main ()
+ {
+ new A ();
+ new B ().Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept]
+ public virtual void Foo ()
+ {
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (B))]
+ class A : B {
+ [Kept]
+ public override void Foo ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/VirtualMethodGetsStrippedIfImplementingMethodGetsInvokedDirectly.cs b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/VirtualMethodGetsStrippedIfImplementingMethodGetsInvokedDirectly.cs
new file mode 100644
index 000000000..d6b4969fe
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Inheritance.VirtualMethods/VirtualMethodGetsStrippedIfImplementingMethodGetsInvokedDirectly.cs
@@ -0,0 +1,27 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Inheritance.VirtualMethods {
+ class VirtualMethodGetsStrippedIfImplementingMethodGetsInvokedDirectly {
+ public static void Main ()
+ {
+ new A ().Foo ();
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept] // TODO: Would be nice to be removed
+ public virtual void Foo ()
+ {
+ }
+ }
+
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (B))]
+ class A : B {
+ [Kept]
+ public override void Foo ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/DefaultConstructorOfParameterIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/DefaultConstructorOfParameterIsRemoved.cs
new file mode 100644
index 000000000..304a78553
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/DefaultConstructorOfParameterIsRemoved.cs
@@ -0,0 +1,23 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls.Com {
+ class DefaultConstructorOfParameterIsRemoved {
+ public static void Main ()
+ {
+ SomeMethod (null);
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern void SomeMethod (A val);
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/DefaultConstructorOfReturnTypeIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/DefaultConstructorOfReturnTypeIsRemoved.cs
new file mode 100644
index 000000000..f9b3fc51d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/DefaultConstructorOfReturnTypeIsRemoved.cs
@@ -0,0 +1,23 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls.Com {
+ class DefaultConstructorOfReturnTypeIsRemoved {
+ public static void Main ()
+ {
+ var a = SomeMethod ();
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern A SomeMethod ();
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfParameterAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfParameterAreRemoved.cs
new file mode 100644
index 000000000..287b00c78
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfParameterAreRemoved.cs
@@ -0,0 +1,24 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls.Com {
+ class FieldsOfParameterAreRemoved {
+ public static void Main ()
+ {
+ SomeMethod (null);
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ private int field;
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern void SomeMethod (A val);
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfReturnTypeAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfReturnTypeAreRemoved.cs
new file mode 100644
index 000000000..d1c0a7ecf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfReturnTypeAreRemoved.cs
@@ -0,0 +1,24 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls.Com {
+ class FieldsOfReturnTypeAreRemoved {
+ public static void Main ()
+ {
+ var a = SomeMethod ();
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ private int field;
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern A SomeMethod ();
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfThisAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfThisAreRemoved.cs
new file mode 100644
index 000000000..ad4918318
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/Com/FieldsOfThisAreRemoved.cs
@@ -0,0 +1,25 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls.Com {
+ class FieldsOfThisAreRemoved {
+ public static void Main ()
+ {
+ new A ().SomeMethod ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ private int field;
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ public extern void SomeMethod ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/DefaultConstructorOfReturnTypeIsNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/DefaultConstructorOfReturnTypeIsNotRemoved.cs
new file mode 100644
index 000000000..ecfe75123
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/DefaultConstructorOfReturnTypeIsNotRemoved.cs
@@ -0,0 +1,22 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls {
+ class DefaultConstructorOfReturnTypeIsNotRemoved {
+ public static void Main ()
+ {
+ var a = SomeMethod ();
+ }
+
+ class A {
+ [Kept]
+ public A ()
+ {
+ }
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern A SomeMethod ();
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedDefaultConstructorIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedDefaultConstructorIsRemoved.cs
new file mode 100644
index 000000000..ab21994f0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedDefaultConstructorIsRemoved.cs
@@ -0,0 +1,27 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls {
+ class UnusedDefaultConstructorIsRemoved {
+ public static void Main ()
+ {
+ var a = new A (1);
+ SomeMethod (a);
+ }
+
+ class A {
+ public A ()
+ {
+ }
+
+ [Kept]
+ public A (int other)
+ {
+ }
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern void SomeMethod (A a);
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs
new file mode 100644
index 000000000..d181ecd0a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs
@@ -0,0 +1,28 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls {
+ class UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved {
+ public static void Main ()
+ {
+ var a = new A (1);
+ SomeMethod (ref a);
+ }
+
+ class A {
+ [Kept]
+ public A ()
+ {
+ }
+
+ [Kept]
+ public A (int other)
+ {
+ }
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern void SomeMethod (ref A a);
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesAreNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesAreNotRemoved.cs
new file mode 100644
index 000000000..09809a60e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesAreNotRemoved.cs
@@ -0,0 +1,23 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls {
+ class UnusedFieldsOfTypesAreNotRemoved {
+ public static void Main ()
+ {
+ var a = new A ();
+ SomeMethod (a);
+ }
+
+ [KeptMember (".ctor()")]
+ class A {
+ [Kept] private int field1;
+
+ [Kept] private int field2;
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern void SomeMethod (A a);
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs
new file mode 100644
index 000000000..d4f3c3779
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs
@@ -0,0 +1,23 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls {
+ class UnusedFieldsOfTypesPassedByRefAreNotRemoved {
+ public static void Main ()
+ {
+ var a = new A ();
+ SomeMethod (ref a);
+ }
+
+ [KeptMember (".ctor()")]
+ class A {
+ [Kept] private int field1;
+
+ [Kept] private int field2;
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern void SomeMethod (ref A a);
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesWhenHasThisAreNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesWhenHasThisAreNotRemoved.cs
new file mode 100644
index 000000000..df77357d6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/InternalCalls/UnusedFieldsOfTypesWhenHasThisAreNotRemoved.cs
@@ -0,0 +1,21 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.InternalCalls {
+ class UnusedFieldsOfTypesWhenHasThisAreNotRemoved {
+ public static void Main ()
+ {
+ A a = new A ();
+ a.SomeMethod ();
+ }
+
+ [KeptMember (".ctor()")]
+ class A {
+ [Kept] private int field1;
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ public extern void SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/DefaultConstructorOfParameterIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/DefaultConstructorOfParameterIsRemoved.cs
new file mode 100644
index 000000000..df3d3b552
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/DefaultConstructorOfParameterIsRemoved.cs
@@ -0,0 +1,23 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Com {
+ class DefaultConstructorOfParameterIsRemoved {
+ public static void Main ()
+ {
+ SomeMethod (null);
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern void SomeMethod (A val);
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/DefaultConstructorOfReturnTypeIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/DefaultConstructorOfReturnTypeIsRemoved.cs
new file mode 100644
index 000000000..3cc7df5db
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/DefaultConstructorOfReturnTypeIsRemoved.cs
@@ -0,0 +1,23 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Com {
+ class DefaultConstructorOfReturnTypeIsRemoved {
+ public static void Main ()
+ {
+ var a = SomeMethod ();
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern A SomeMethod ();
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfParameterAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfParameterAreRemoved.cs
new file mode 100644
index 000000000..73a66b576
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfParameterAreRemoved.cs
@@ -0,0 +1,24 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Com {
+ class FieldsOfParameterAreRemoved {
+ public static void Main ()
+ {
+ SomeMethod (null);
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ private int field;
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern void SomeMethod (A val);
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfReturnTypeAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfReturnTypeAreRemoved.cs
new file mode 100644
index 000000000..7551d8687
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfReturnTypeAreRemoved.cs
@@ -0,0 +1,24 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Com {
+ class FieldsOfReturnTypeAreRemoved {
+ public static void Main ()
+ {
+ var a = SomeMethod ();
+ }
+
+ [Kept]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ private int field;
+ }
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern A SomeMethod ();
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfThisAreRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfThisAreRemoved.cs
new file mode 100644
index 000000000..4c7402063
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/Com/FieldsOfThisAreRemoved.cs
@@ -0,0 +1,25 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke.Com {
+ class FieldsOfThisAreRemoved {
+ public static void Main ()
+ {
+ new A ().SomeMethod ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof (GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A {
+ private int field;
+
+ [Kept]
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ public extern void SomeMethod ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/DefaultConstructorOfReturnTypeIsNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/DefaultConstructorOfReturnTypeIsNotRemoved.cs
new file mode 100644
index 000000000..d714d0d95
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/DefaultConstructorOfReturnTypeIsNotRemoved.cs
@@ -0,0 +1,22 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke {
+ class DefaultConstructorOfReturnTypeIsNotRemoved {
+ public static void Main ()
+ {
+ var a = SomeMethod ();
+ }
+
+ class A {
+ [Kept]
+ public A ()
+ {
+ }
+ }
+
+ [Kept]
+ [DllImport ("Unused")]
+ private static extern A SomeMethod ();
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedDefaultConstructorIsRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedDefaultConstructorIsRemoved.cs
new file mode 100644
index 000000000..041cc9c98
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedDefaultConstructorIsRemoved.cs
@@ -0,0 +1,27 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke {
+ class UnusedDefaultConstructorIsRemoved {
+ public static void Main ()
+ {
+ var a = new A (1);
+ SomeMethod (a);
+ }
+
+ class A {
+ public A ()
+ {
+ }
+
+ [Kept]
+ public A (int other)
+ {
+ }
+ }
+
+ [Kept]
+ [DllImport ("Unused")]
+ private static extern void SomeMethod (A a);
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs
new file mode 100644
index 000000000..db2514a4a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs
@@ -0,0 +1,28 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke {
+ class UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved {
+ public static void Main ()
+ {
+ var a = new A (1);
+ SomeMethod (ref a);
+ }
+
+ class A {
+ [Kept]
+ public A ()
+ {
+ }
+
+ [Kept]
+ public A (int other)
+ {
+ }
+ }
+
+ [Kept]
+ [DllImport ("Unused")]
+ private static extern void SomeMethod (ref A a);
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedFieldsOfTypesAreNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedFieldsOfTypesAreNotRemoved.cs
new file mode 100644
index 000000000..a34c4d6bb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedFieldsOfTypesAreNotRemoved.cs
@@ -0,0 +1,23 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke {
+ class UnusedFieldsOfTypesAreNotRemoved {
+ public static void Main ()
+ {
+ var a = new A ();
+ SomeMethod (a);
+ }
+
+ [KeptMember (".ctor()")]
+ class A {
+ [Kept] private int field1;
+
+ [Kept] private int field2;
+ }
+
+ [Kept]
+ [DllImport ("Unused")]
+ private static extern void SomeMethod (A a);
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs
new file mode 100644
index 000000000..50ae45fe3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Interop/PInvoke/UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs
@@ -0,0 +1,23 @@
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Interop.PInvoke {
+ class UnusedFieldsOfTypesPassedByRefAreNotRemoved {
+ public static void Main ()
+ {
+ var a = new A ();
+ SomeMethod (ref a);
+ }
+
+ [KeptMember (".ctor()")]
+ class A {
+ [Kept] private int field1;
+
+ [Kept] private int field2;
+ }
+
+ [Kept]
+ [DllImport ("Unused")]
+ private static extern void SomeMethod (ref A a);
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Libraries/CanLinkPublicApisOfLibrary.cs b/test/Mono.Linker.Tests.Cases/Libraries/CanLinkPublicApisOfLibrary.cs
new file mode 100644
index 000000000..1bcd525dd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Libraries/CanLinkPublicApisOfLibrary.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Libraries {
+ [SetupLinkerLinkPublicAndFamily]
+ [SetupCompileAsLibrary]
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class CanLinkPublicApisOfLibrary {
+ // Kept because by default libraries their action set to copy
+ [Kept]
+ public static void Main ()
+ {
+ // Main is needed for the test collector to find and treat as a test
+ }
+
+ [Kept]
+ public void UnusedPublicMethod ()
+ {
+ }
+
+ private void UnusedPrivateMethod ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Libraries/DefaultLibraryLinkBehavior.cs b/test/Mono.Linker.Tests.Cases/Libraries/DefaultLibraryLinkBehavior.cs
new file mode 100644
index 000000000..5c1e9aba4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Libraries/DefaultLibraryLinkBehavior.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Libraries {
+ [SetupCompileAsLibrary]
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class DefaultLibraryLinkBehavior {
+ // Kept because by default libraries their action set to copy
+ [Kept]
+ public static void Main ()
+ {
+ // Main is needed for the test collector to find and treat as a test
+ }
+
+ [Kept]
+ public void UnusedPublicMethod ()
+ {
+ }
+
+ [Kept]
+ private void UnusedPrivateMethod ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Libraries/Dependencies/UserAssemblyActionWorks_Lib.cs b/test/Mono.Linker.Tests.Cases/Libraries/Dependencies/UserAssemblyActionWorks_Lib.cs
new file mode 100644
index 000000000..b9b9e5863
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Libraries/Dependencies/UserAssemblyActionWorks_Lib.cs
@@ -0,0 +1,11 @@
+namespace Mono.Linker.Tests.Cases.Libraries.Dependencies {
+ public class UserAssemblyActionWorks_Lib {
+ public static void Used ()
+ {
+ }
+
+ public static void Unused ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Libraries/UserAssemblyActionWorks.cs b/test/Mono.Linker.Tests.Cases/Libraries/UserAssemblyActionWorks.cs
new file mode 100644
index 000000000..1337ce066
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Libraries/UserAssemblyActionWorks.cs
@@ -0,0 +1,18 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Libraries.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Libraries {
+ /// <summary>
+ /// We have to check another assembly because the test exe is included with -a and that will cause it to be linked
+ /// </summary>
+ [SetupLinkerUserAction ("copy")]
+ [SetupCompileBefore ("lib.dll", new[] { "Dependencies/UserAssemblyActionWorks_Lib.cs" })]
+ [KeptAllTypesAndMembersInAssembly ("lib.dll")]
+ public class UserAssemblyActionWorks {
+ public static void Main ()
+ {
+ UserAssemblyActionWorks_Lib.Used ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/AssemblyWithPreserveAll.cs b/test/Mono.Linker.Tests.Cases/LinkXml/AssemblyWithPreserveAll.cs
new file mode 100644
index 000000000..f02913bc5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/AssemblyWithPreserveAll.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ [KeptMember (".ctor()")]
+ public class AssemblyWithPreserveAll {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class UnusedType {
+ [Kept]
+ public int UnusedField;
+
+ [Kept]
+ [KeptBackingField]
+ public int UnusedProperty { [Kept] get; [Kept] set; }
+
+ [Kept]
+ public void UnusedMethod ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class UnusedNestedType {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/AssemblyWithPreserveAll.xml b/test/Mono.Linker.Tests.Cases/LinkXml/AssemblyWithPreserveAll.xml
new file mode 100644
index 000000000..a1a96721e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/AssemblyWithPreserveAll.xml
@@ -0,0 +1,4 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" preserve="all">
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.cs b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.cs
new file mode 100644
index 000000000..bbf26c1d4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.cs
@@ -0,0 +1,19 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.LinkXml.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.LinkXml
+{
+ [KeepTypeForwarderOnlyAssemblies ("false")]
+ [SetupCompileBefore ("Library.dll", new[] { "Dependencies/CanPreserveAnExportedType_Library.cs" })]
+ // Add another assembly in that uses the forwarder just to make things a little more complex
+ [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/CanPreserveAnExportedType_Forwarder.cs" }, references: new[] { "Library.dll" })]
+
+ [RemovedAssembly ("Forwarder.dll")]
+ [KeptMemberInAssembly ("Library.dll", typeof (CanPreserveAnExportedType_Library), "Field1", "Method()", ".ctor()")]
+ class CanPreserveAnExportedType {
+ public static void Main () {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.xml b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.xml
new file mode 100644
index 000000000..f469bb982
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveAnExportedType.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.Dependencies.CanPreserveAnExportedType_Library" preserve="all">
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExcludedFeatureCom.cs b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExcludedFeatureCom.cs
new file mode 100644
index 000000000..0016d7272
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExcludedFeatureCom.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Runtime.InteropServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ [SetupLinkerArgument ("--exclude-feature", "com")]
+ public class CanPreserveExcludedFeatureCom {
+ public static void Main()
+ {
+ var a = new A ();
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptAttributeAttribute (typeof(GuidAttribute))]
+ [ComImport]
+ [Guid ("D7BB1889-3AB7-4681-A115-60CA9158FECA")]
+ class A
+ {
+ private int field;
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExcludedFeatureCom.xml b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExcludedFeatureCom.xml
new file mode 100644
index 000000000..bcd942aaf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExcludedFeatureCom.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="mscorlib">
+ <type fullname="System.Runtime.InteropServices.GuidAttribute" preserve="all">
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.cs b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.cs
new file mode 100644
index 000000000..d122d98f3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.cs
@@ -0,0 +1,19 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.LinkXml.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.LinkXml
+{
+ [KeepTypeForwarderOnlyAssemblies ("false")]
+ [SetupCompileBefore ("Library.dll", new [] { "Dependencies/CanPreserveAnExportedType_Library.cs" })]
+ // Add another assembly in that uses the forwarder just to make things a little more complex
+ [SetupCompileBefore ("Forwarder.dll", new [] { "Dependencies/CanPreserveAnExportedType_Forwarder.cs" }, references: new [] { "Library.dll" })]
+
+ [RemovedAssembly ("Forwarder.dll")]
+ [KeptMemberInAssembly ("Library.dll", typeof (CanPreserveAnExportedType_Library), "Field1", "Method()", ".ctor()")]
+ class CanPreserveExportedTypesUsingRegex {
+ public static void Main () {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.xml b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.xml
new file mode 100644
index 000000000..b5827e265
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveExportedTypesUsingRegex.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Can*" preserve="all">
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveTypesUsingRegex.cs b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveTypesUsingRegex.cs
new file mode 100644
index 000000000..0eb9542d2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveTypesUsingRegex.cs
@@ -0,0 +1,32 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml
+{
+ [KeptMember (".ctor()")]
+ class CanPreserveTypesUsingRegex {
+ public static void Main () {
+ }
+
+ [Kept]
+ void UnusedHelper () {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Bar {
+ }
+ }
+}
+
+namespace Mono.Linker.Tests.Cases.LinkXml.PreserveNamespace {
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Type1 {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Type2 {
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveTypesUsingRegex.xml b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveTypesUsingRegex.xml
new file mode 100644
index 000000000..12f870c04
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/CanPreserveTypesUsingRegex.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Can*" />
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.PreserveNamespace*" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/CanPreserveAnExportedType_Forwarder.cs b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/CanPreserveAnExportedType_Forwarder.cs
new file mode 100644
index 000000000..cb6f81e48
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/CanPreserveAnExportedType_Forwarder.cs
@@ -0,0 +1,3 @@
+using System;
+
+[assembly: System.Runtime.CompilerServices.TypeForwardedTo (typeof (Mono.Linker.Tests.Cases.LinkXml.Dependencies.CanPreserveAnExportedType_Library))]
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/CanPreserveAnExportedType_Library.cs b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/CanPreserveAnExportedType_Library.cs
new file mode 100644
index 000000000..38814d986
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/CanPreserveAnExportedType_Library.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.LinkXml.Dependencies
+{
+ public class CanPreserveAnExportedType_Library {
+ public int Field1;
+
+ public void Method () {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Base.cs b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Base.cs
new file mode 100644
index 000000000..d9803fada
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Base.cs
@@ -0,0 +1,7 @@
+namespace Mono.Linker.Tests.Cases.LinkXml.Dependencies.EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod {
+ public class Base {
+ public virtual void VirtualMethodFromBase ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.cs b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.cs
new file mode 100644
index 000000000..3c1158922
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.cs
@@ -0,0 +1,17 @@
+namespace Mono.Linker.Tests.Cases.LinkXml.Dependencies.EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod {
+ public class Library1 : Base {
+ public override void VirtualMethodFromBase ()
+ {
+ }
+ }
+
+ /// <summary>
+ /// This is here to confirm that derived types in the same assembly as the embedded resource are correctly taken into
+ /// consideration
+ /// </summary>
+ public class Library1Secondary : Base {
+ public override void VirtualMethodFromBase ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.xml b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.xml
new file mode 100644
index 000000000..58f90df91
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.xml
@@ -0,0 +1,14 @@
+<linker>
+ <assembly fullname="Library1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.Dependencies.EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod.Library1Secondary" preserve="nothing">
+ <!-- Need to preserve a ctor so that an instance of the type is possible-->
+ <method name=".ctor"/>
+ </type>
+ </assembly>
+ <assembly fullname="Library2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.Dependencies.EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod.Library2" preserve="nothing">
+ <!-- Need to preserve a ctor so that an instance of the type is possible-->
+ <method name=".ctor"/>
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library2.cs b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library2.cs
new file mode 100644
index 000000000..b977a5834
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library2.cs
@@ -0,0 +1,7 @@
+namespace Mono.Linker.Tests.Cases.LinkXml.Dependencies.EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod {
+ public class Library2 : Base {
+ public override void VirtualMethodFromBase ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod.cs b/test/Mono.Linker.Tests.Cases/LinkXml/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod.cs
new file mode 100644
index 000000000..6111bc713
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.LinkXml.Dependencies.EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ [SetupCompileBefore ("Base.dll",
+ new []{"Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Base.cs"})]
+ [SetupCompileBefore ("Library1.dll",
+ new [] { "Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.cs"},
+ new [] { "Base.dll"},
+ resources: new [] { "Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library1.xml"})]
+ [SetupCompileBefore("Library2.dll",
+ new [] {"Dependencies/EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod/Library2.cs"},
+ new [] {"Base.dll"},
+ addAsReference: false)]
+ [IncludeBlacklistStep (true)]
+
+ [KeptMemberInAssembly ("Library1.dll", typeof (Library1), "VirtualMethodFromBase()")]
+ [KeptMemberInAssembly ("Library1.dll", typeof (Library1Secondary), "VirtualMethodFromBase()")]
+
+ // Library1's embedded link xml will preserve the Library2 type. Because Library2 shares a base class with Library1
+ // Library2's override should be kept as well
+ [KeptMemberInAssembly ("Library2.dll", "Mono.Linker.Tests.Cases.LinkXml.Dependencies.EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod.Library2", "VirtualMethodFromBase()")]
+ public class EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod {
+ public static void Main ()
+ {
+ var tmp = new Library1 ();
+ tmp.VirtualMethodFromBase ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/Dependencies/OnAssembly_Lib1.cs b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/Dependencies/OnAssembly_Lib1.cs
new file mode 100644
index 000000000..1e0c0a738
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/Dependencies/OnAssembly_Lib1.cs
@@ -0,0 +1,10 @@
+namespace Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.Dependencies {
+ public class OnAssembly_Lib1 {
+ public static void UsedSoCompilerDoesntRemoveReference ()
+ {
+ }
+
+ public class FeatureOneClass {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/Dependencies/OnAssembly_Lib2.cs b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/Dependencies/OnAssembly_Lib2.cs
new file mode 100644
index 000000000..0a7731e79
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/Dependencies/OnAssembly_Lib2.cs
@@ -0,0 +1,10 @@
+namespace Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.Dependencies {
+ public class OnAssembly_Lib2 {
+ public static void UsedSoCompilerDoesntRemoveReference ()
+ {
+ }
+
+ public class FeatureTwoClass {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnAssembly.cs b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnAssembly.cs
new file mode 100644
index 000000000..cbdfb5509
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnAssembly.cs
@@ -0,0 +1,18 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.LinkXml.FeatureExclude {
+ [SetupLinkerArgument ("--exclude-feature", "one")]
+ [SetupCompileBefore ("library1.dll", new[] {typeof (OnAssembly_Lib1)})]
+ [SetupCompileBefore ("library2.dll", new[] {typeof (OnAssembly_Lib2)})]
+ [RemovedTypeInAssembly ("library1.dll", typeof (OnAssembly_Lib1.FeatureOneClass))]
+ [KeptTypeInAssembly ("library2.dll", typeof (OnAssembly_Lib2.FeatureTwoClass))]
+ public class OnAssembly {
+ public static void Main ()
+ {
+ OnAssembly_Lib1.UsedSoCompilerDoesntRemoveReference ();
+ OnAssembly_Lib2.UsedSoCompilerDoesntRemoveReference ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnAssembly.xml b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnAssembly.xml
new file mode 100644
index 000000000..9583b20ee
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnAssembly.xml
@@ -0,0 +1,8 @@
+<linker>
+ <assembly fullname="library1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" feature="one">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.Dependencies.OnAssembly_Lib1/FeatureOneClass"/>
+ </assembly>
+ <assembly fullname="library2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" feature="two">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.Dependencies.OnAssembly_Lib2/FeatureTwoClass"/>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnEvent.cs b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnEvent.cs
new file mode 100644
index 000000000..e733ab2d1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnEvent.cs
@@ -0,0 +1,17 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.LinkXml.FeatureExclude {
+ [SetupLinkerArgument ("--exclude-feature", "one")]
+ public class OnEvent {
+ public static void Main ()
+ {
+ }
+
+ public event EventHandler<EventArgs> FeatureOne;
+
+ [Kept]
+ public event EventHandler<EventArgs> FeatureTwo {[Kept] add {}[Kept] remove {} }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnEvent.xml b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnEvent.xml
new file mode 100644
index 000000000..d0fdc860d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnEvent.xml
@@ -0,0 +1,10 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnEvent">
+ <event signature="System.EventHandler`1&lt;System.EventArgs&gt; FeatureOne" feature="one"/>
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnEvent">
+ <event signature="System.EventHandler`1&lt;System.EventArgs&gt; FeatureTwo" feature="two"/>
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnField.cs b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnField.cs
new file mode 100644
index 000000000..93a61f0ab
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnField.cs
@@ -0,0 +1,16 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.LinkXml.FeatureExclude {
+ [SetupLinkerArgument ("--exclude-feature", "one")]
+ public class OnField {
+ public static void Main ()
+ {
+ }
+
+ private int _featureOne;
+
+ [Kept]
+ private int _featureTwo;
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnField.xml b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnField.xml
new file mode 100644
index 000000000..b7a251bf8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnField.xml
@@ -0,0 +1,10 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnField">
+ <field signature="System.Int32 _featureOne" feature="one"/>
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnField">
+ <field signature="System.Int32 _featureTwo" feature="two"/>
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnMethod.cs b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnMethod.cs
new file mode 100644
index 000000000..11feb7a6a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnMethod.cs
@@ -0,0 +1,20 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.LinkXml.FeatureExclude {
+ [SetupLinkerArgument ("--exclude-feature", "one")]
+ public class OnMethod {
+ public static void Main ()
+ {
+ }
+
+ public void FeatureOne ()
+ {
+ }
+
+ [Kept]
+ public void FeatureTwo ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnMethod.xml b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnMethod.xml
new file mode 100644
index 000000000..5aaf4c06f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnMethod.xml
@@ -0,0 +1,10 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnMethod">
+ <method signature="System.Void FeatureOne()" feature="one"/>
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnMethod">
+ <method signature="System.Void FeatureTwo()" feature="two"/>
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnProperty.cs b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnProperty.cs
new file mode 100644
index 000000000..b6e78b255
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnProperty.cs
@@ -0,0 +1,17 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.LinkXml.FeatureExclude {
+ [SetupLinkerArgument ("--exclude-feature", "one")]
+ public class OnProperty {
+ public static void Main ()
+ {
+ }
+
+ public int FeatureOne { get; set; }
+
+ [Kept]
+ [KeptBackingField]
+ public int FeatureTwo {[Kept] get; [Kept] set; }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnProperty.xml b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnProperty.xml
new file mode 100644
index 000000000..3b2ee6fcb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnProperty.xml
@@ -0,0 +1,10 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnProperty">
+ <property signature="System.Int32 FeatureOne" accessors="all" feature="one"/>
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnProperty">
+ <property signature="System.Int32 FeatureTwo" accessors="all" feature="two"/>
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnType.cs b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnType.cs
new file mode 100644
index 000000000..368812fcc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnType.cs
@@ -0,0 +1,20 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.LinkXml.FeatureExclude {
+ [SetupLinkerArgument ("--exclude-feature", "one")]
+ public class OnType {
+ public static void Main ()
+ {
+ }
+
+ class FeatureOneClass
+ {
+ }
+
+ [Kept]
+ [KeptMember(".ctor()")]
+ class FeatureTwoClass {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnType.xml b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnType.xml
new file mode 100644
index 000000000..a2e91e062
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/FeatureExclude/OnType.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnType/FeatureOneClass" feature="one"/>
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.FeatureExclude.OnType/FeatureTwoClass" feature="two"/>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/PreserveBackingFieldWhenPropertyIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/PreserveBackingFieldWhenPropertyIsKept.cs
new file mode 100644
index 000000000..c319c1442
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/PreserveBackingFieldWhenPropertyIsKept.cs
@@ -0,0 +1,18 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml
+{
+ abstract class PreserveBackingFieldWhenPropertyIsKept
+ {
+ public static void Main ()
+ {
+ Prop = 1;
+ }
+
+ public abstract int Base { set; }
+
+ [Kept]
+ [KeptBackingField]
+ public static int Prop { get; [Kept] set; }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/PreserveBackingFieldWhenPropertyIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/PreserveBackingFieldWhenPropertyIsKept.xml
new file mode 100644
index 000000000..256f50a84
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/PreserveBackingFieldWhenPropertyIsKept.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.PreserveBackingFieldWhenPropertyIsKept" preserve="fields">
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.cs
new file mode 100644
index 000000000..623ee17ca
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.cs
@@ -0,0 +1,61 @@
+
+
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml
+{
+ class TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved {
+ public static void Main () {
+ }
+
+ [Kept]
+ class Unused : IFoo<int>, IFoo<string>, IFoo<Cat>, IFoo2<int>, IFoo3<int, string, char>, IDog, IFoo<IFoo<int>> {
+ [Kept]
+ public int Field1;
+
+ [Kept]
+ public IFoo<int> Field2;
+
+ public IFoo<int> Property1 { get; set; }
+
+ string IDog.Name { get; set; }
+
+ int IFoo<int>.Bar { get; set; }
+
+ int IFoo<string>.Bar { get; set; }
+
+ int IFoo<Cat>.Bar { get; set; }
+
+ int Bar2 { get; set; }
+
+ int IFoo2<int>.Bar2 { get; set; }
+
+ int Bar3 { get; set; }
+
+ int IFoo3<int, string, char>.Bar3 { get; set; }
+
+ int IFoo<IFoo<int>>.Bar { get; set; }
+ }
+
+ interface IDog {
+ string Name { get; set; }
+ }
+
+ [Kept]
+ interface IFoo<T> {
+
+ int Bar { get; set; }
+ }
+
+ interface IFoo2<T> {
+ int Bar2 { get; set; }
+ }
+
+ interface IFoo3<T, K, J> {
+ int Bar3 { get; set; }
+ }
+
+ class Cat {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.xml
new file mode 100644
index 000000000..338ee7f76
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved/Unused" preserve="fields">
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.cs
new file mode 100644
index 000000000..fb8536a2f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.cs
@@ -0,0 +1,15 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ [KeptMember (".ctor()")]
+ public class UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Unused {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.xml
new file mode 100644
index 000000000..ca7da2c44
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.xml
@@ -0,0 +1,4 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedEventPreservedByLinkXmlIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedEventPreservedByLinkXmlIsKept.cs
new file mode 100644
index 000000000..594b5bd87
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedEventPreservedByLinkXmlIsKept.cs
@@ -0,0 +1,37 @@
+using System;
+
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedEventPreservedByLinkXmlIsKept {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ class Unused {
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event EventHandler<EventArgs> Preserved;
+
+ [Kept]
+ public event EventHandler<EventArgs> Preserved1 { [Kept] add { } [Kept] remove { } }
+
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event EventHandler Preserved2;
+
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ public event EventHandler Preserved3;
+
+ public event EventHandler<EventArgs> NotPreserved;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedEventPreservedByLinkXmlIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedEventPreservedByLinkXmlIsKept.xml
new file mode 100644
index 000000000..027cc59d1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedEventPreservedByLinkXmlIsKept.xml
@@ -0,0 +1,10 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedEventPreservedByLinkXmlIsKept/Unused">
+ <event signature="System.EventHandler`1&lt;System.EventArgs&gt; Preserved" />
+ <event signature="System.EventHandler`1&lt;System.EventArgs&gt; Preserved1" />
+ <event signature="System.EventHandler Preserved2" />
+ <event name="Preserved3" />
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedFieldPreservedByLinkXmlIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedFieldPreservedByLinkXmlIsKept.cs
new file mode 100644
index 000000000..d41e23716
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedFieldPreservedByLinkXmlIsKept.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedFieldPreservedByLinkXmlIsKept {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ class Unused {
+ [Kept]
+ private int _preserved;
+
+ [Kept]
+ private int _preserved2;
+
+ [Kept]
+ private List<int> _preserved3;
+
+ private int _notPreserved;
+ }
+
+ [Kept]
+ class UnusedWithGenerics<T> {
+ [Kept]
+ private List<T> _preserved1;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedFieldPreservedByLinkXmlIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedFieldPreservedByLinkXmlIsKept.xml
new file mode 100644
index 000000000..82daa710c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedFieldPreservedByLinkXmlIsKept.xml
@@ -0,0 +1,12 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedFieldPreservedByLinkXmlIsKept/Unused">
+ <field signature="System.Int32 _preserved" />
+ <field name="_preserved2" />
+ <field signature="System.Collections.Generic.List`1&lt;System.Int32&gt; _preserved3" />
+ </type>
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedFieldPreservedByLinkXmlIsKept/UnusedWithGenerics`1">
+ <field signature="System.Collections.Generic.List`1&lt;T&gt; _preserved1" />
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.cs
new file mode 100644
index 000000000..659d4c5d1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.cs
@@ -0,0 +1,85 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ public class UnusedGenericTypeWithPreserveAllHasAllMembersPreserved {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Unused<T1, T2, T3> {
+ [Kept]
+ public int Field1;
+
+ [Kept]
+ private int Field2;
+
+ [Kept]
+ internal int Field3;
+
+ [Kept]
+ public static int Field4;
+
+ [Kept]
+ private static int Field5;
+
+ [Kept]
+ internal static int Field6;
+
+ [Kept]
+ [KeptBackingField]
+ public string Property1 { [Kept] get; [Kept] set;}
+
+ [Kept]
+ [KeptBackingField]
+ private string Property2 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ internal string Property3 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public static string Property4 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ private static string Property5 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ internal static string Property6 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ public void Method1 ()
+ {
+ }
+
+ [Kept]
+ private void Method2 ()
+ {
+ }
+
+ [Kept]
+ internal void Method3 ()
+ {
+ }
+
+ [Kept]
+ public static void Method4 ()
+ {
+ }
+
+ [Kept]
+ private static void Method5 ()
+ {
+ }
+
+ [Kept]
+ internal static void Method6 ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.xml
new file mode 100644
index 000000000..b2da72420
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedGenericTypeWithPreserveAllHasAllMembersPreserved/Unused`3" preserve="all" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.cs
new file mode 100644
index 000000000..8e362a4d8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.cs
@@ -0,0 +1,19 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ public class UnusedInterfaceTypeOnTypeWithPreserveAllIsKept {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ interface IFoo {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptInterface (typeof (IFoo))]
+ class Bar : IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.xml
new file mode 100644
index 000000000..48d80c17d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedInterfaceTypeOnTypeWithPreserveAllIsKept/Bar" preserve="all"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.cs
new file mode 100644
index 000000000..968d0d1e6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.cs
@@ -0,0 +1,16 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ public class UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved {
+ public static void Main ()
+ {
+ }
+
+ interface IFoo {
+ }
+
+ [Kept]
+ class Bar : IFoo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.xml
new file mode 100644
index 000000000..0cd063a84
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved/Bar" preserve="nothing"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedMethodPreservedByLinkXmlIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedMethodPreservedByLinkXmlIsKept.cs
new file mode 100644
index 000000000..9fe2b353b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedMethodPreservedByLinkXmlIsKept.cs
@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedMethodPreservedByLinkXmlIsKept {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ class Unused {
+ [Kept]
+ private void PreservedMethod ()
+ {
+ }
+
+ [Kept]
+ private void PreservedMethod2 (int arg1, string arg2)
+ {
+ }
+
+ [Kept]
+ private void PreservedMethod3 ()
+ {
+ }
+
+ [Kept]
+ private void PreservedMethod4 (List<int> arg1)
+ {
+ }
+
+ private void NotPreservedMethod ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedMethodPreservedByLinkXmlIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedMethodPreservedByLinkXmlIsKept.xml
new file mode 100644
index 000000000..d5af5b146
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedMethodPreservedByLinkXmlIsKept.xml
@@ -0,0 +1,10 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedMethodPreservedByLinkXmlIsKept/Unused">
+ <method signature="System.Void PreservedMethod()" />
+ <method signature="System.Void PreservedMethod2(System.Int32,System.String)" />
+ <method name="PreservedMethod3" />
+ <method signature="System.Void PreservedMethod4(System.Collections.Generic.List`1&lt;System.Int32&gt;)" />
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNestedTypePreservedByLinkXmlIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNestedTypePreservedByLinkXmlIsKept.cs
new file mode 100644
index 000000000..5e319acfd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNestedTypePreservedByLinkXmlIsKept.cs
@@ -0,0 +1,14 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedNestedTypePreservedByLinkXmlIsKept {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Unused {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNestedTypePreservedByLinkXmlIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNestedTypePreservedByLinkXmlIsKept.xml
new file mode 100644
index 000000000..7990e8fec
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNestedTypePreservedByLinkXmlIsKept.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedNestedTypePreservedByLinkXmlIsKept/Unused" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNonRequiredTypeIsRemoved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNonRequiredTypeIsRemoved.cs
new file mode 100644
index 000000000..8175ee32e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNonRequiredTypeIsRemoved.cs
@@ -0,0 +1,10 @@
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ public class UnusedNonRequiredTypeIsRemoved {
+ public static void Main ()
+ {
+ }
+
+ class Unused {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNonRequiredTypeIsRemoved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNonRequiredTypeIsRemoved.xml
new file mode 100644
index 000000000..168b5aa2c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedNonRequiredTypeIsRemoved.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedNonRequiredTypeIsRemoved/Unused" preserve="all" required="0"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedPropertyPreservedByLinkXmlIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedPropertyPreservedByLinkXmlIsKept.cs
new file mode 100644
index 000000000..6f21e7b55
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedPropertyPreservedByLinkXmlIsKept.cs
@@ -0,0 +1,46 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedPropertyPreservedByLinkXmlIsKept {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ class Unused {
+ [Kept]
+ [KeptBackingField]
+ public int PreservedProperty1 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public int PreservedProperty2 { [Kept] get; set; }
+
+ [Kept]
+ [KeptBackingField]
+ public int PreservedProperty3 { get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public int PreservedProperty4 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public int PreservedProperty5 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public int PreservedProperty6 { [Kept] get; set; }
+
+ [Kept]
+ [KeptBackingField]
+ public int PreservedProperty7 { get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public int PreservedProperty8 { [Kept] get; [Kept] set; }
+
+ public int NotPreservedProperty { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedPropertyPreservedByLinkXmlIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedPropertyPreservedByLinkXmlIsKept.xml
new file mode 100644
index 000000000..c606c5445
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedPropertyPreservedByLinkXmlIsKept.xml
@@ -0,0 +1,17 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedPropertyPreservedByLinkXmlIsKept/Unused">
+ <method signature="System.Int32 get_PreservedProperty1()" />
+ <method signature="System.Void set_PreservedProperty1(System.Int32)" />
+ <method signature="System.Int32 get_PreservedProperty2()" />
+ <method signature="System.Void set_PreservedProperty3(System.Int32)" />
+
+ <property signature="System.Int32 PreservedProperty4" />
+ <property signature="System.Int32 PreservedProperty5" accessors="all" />
+ <property signature="System.Int32 PreservedProperty6" accessors="get" />
+ <property signature="System.Int32 PreservedProperty7" accessors="set" />
+
+ <property name="PreservedProperty8" />
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeDeclarationPreservedByLinkXmlIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeDeclarationPreservedByLinkXmlIsKept.cs
new file mode 100644
index 000000000..bd2b15ba3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeDeclarationPreservedByLinkXmlIsKept.cs
@@ -0,0 +1,27 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ public class UnusedTypeDeclarationPreservedByLinkXmlIsKept {
+ public static void Main ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (UnusedTypeDeclarationPreservedByLinkXmlIsKeptUnusedTypeBase))]
+ class UnusedTypeDeclarationPreservedByLinkXmlIsKeptUnusedType : UnusedTypeDeclarationPreservedByLinkXmlIsKeptUnusedTypeBase
+ {
+ int field;
+ static void Method ()
+ {
+ }
+
+ string Prop { get; set; }
+ }
+
+ [Kept]
+ class UnusedTypeDeclarationPreservedByLinkXmlIsKeptUnusedTypeBase
+ {
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeDeclarationPreservedByLinkXmlIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeDeclarationPreservedByLinkXmlIsKept.xml
new file mode 100644
index 000000000..c99f6b46b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeDeclarationPreservedByLinkXmlIsKept.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypeDeclarationPreservedByLinkXmlIsKeptUnusedType" preserve="nothing" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.cs
new file mode 100644
index 000000000..246c80af6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.cs
@@ -0,0 +1,20 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+
+ [KeptMember(".ctor()")]
+ class UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Unused {
+ [Kept]
+ void Foo ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.xml
new file mode 100644
index 000000000..7ecdb6c22
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.xml
@@ -0,0 +1,3 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" preserve="all" />
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlIsKept.cs
new file mode 100644
index 000000000..edaff63eb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlIsKept.cs
@@ -0,0 +1,14 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedTypePreservedByLinkXmlIsKept {
+ public static void Main ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class UnusedTypePreservedByLinkXmlIsKeptUnusedType {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlIsKept.xml
new file mode 100644
index 000000000..ffb652e1e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlIsKept.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypePreservedByLinkXmlIsKeptUnusedType" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlWithCommentIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlWithCommentIsKept.cs
new file mode 100644
index 000000000..fe077d530
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlWithCommentIsKept.cs
@@ -0,0 +1,15 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedTypePreservedByLinkXmlWithCommentIsKept {
+ public static void Main ()
+ {
+ }
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class UnusedTypePreservedByLinkXmlWithCommentIsKeptUnusedType
+ {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlWithCommentIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlWithCommentIsKept.xml
new file mode 100644
index 000000000..a6e5643a2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypePreservedByLinkXmlWithCommentIsKept.xml
@@ -0,0 +1,6 @@
+<!-- this is a comment -->
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypePreservedByLinkXmlWithCommentIsKeptUnusedType" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.cs
new file mode 100644
index 000000000..840d7f474
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.cs
@@ -0,0 +1,86 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved
+ {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Unused {
+ [Kept]
+ public int Field1;
+
+ [Kept]
+ private int Field2;
+
+ [Kept]
+ internal int Field3;
+
+ [Kept]
+ public static int Field4;
+
+ [Kept]
+ private static int Field5;
+
+ [Kept]
+ internal static int Field6;
+
+ [Kept]
+ [KeptBackingField]
+ public string Property1 { [Kept] get; [Kept] set;}
+
+ [Kept]
+ [KeptBackingField]
+ private string Property2 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ internal string Property3 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public static string Property4 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ private static string Property5 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ internal static string Property6 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ public void Method1 ()
+ {
+ }
+
+ [Kept]
+ private void Method2 ()
+ {
+ }
+
+ [Kept]
+ internal void Method3 ()
+ {
+ }
+
+ [Kept]
+ public static void Method4 ()
+ {
+ }
+
+ [Kept]
+ private static void Method5 ()
+ {
+ }
+
+ [Kept]
+ internal static void Method6 ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.xml
new file mode 100644
index 000000000..d84df95e0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved/Unused" />
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveAllHasAllMembersPreserved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveAllHasAllMembersPreserved.cs
new file mode 100644
index 000000000..02fb956f2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveAllHasAllMembersPreserved.cs
@@ -0,0 +1,85 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedTypeWithPreserveAllHasAllMembersPreserved {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Unused {
+ [Kept]
+ public int Field1;
+
+ [Kept]
+ private int Field2;
+
+ [Kept]
+ internal int Field3;
+
+ [Kept]
+ public static int Field4;
+
+ [Kept]
+ private static int Field5;
+
+ [Kept]
+ internal static int Field6;
+
+ [Kept]
+ [KeptBackingField]
+ public string Property1 { [Kept] get; [Kept] set;}
+
+ [Kept]
+ [KeptBackingField]
+ private string Property2 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ internal string Property3 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public static string Property4 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ private static string Property5 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ internal static string Property6 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ public void Method1 ()
+ {
+ }
+
+ [Kept]
+ private void Method2 ()
+ {
+ }
+
+ [Kept]
+ internal void Method3 ()
+ {
+ }
+
+ [Kept]
+ public static void Method4 ()
+ {
+ }
+
+ [Kept]
+ private static void Method5 ()
+ {
+ }
+
+ [Kept]
+ internal static void Method6 ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveAllHasAllMembersPreserved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveAllHasAllMembersPreserved.xml
new file mode 100644
index 000000000..7987a7765
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveAllHasAllMembersPreserved.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypeWithPreserveAllHasAllMembersPreserved/Unused" preserve="all" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveFieldsHasMethodsRemoved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveFieldsHasMethodsRemoved.cs
new file mode 100644
index 000000000..1af6f4530
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveFieldsHasMethodsRemoved.cs
@@ -0,0 +1,66 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedTypeWithPreserveFieldsHasMethodsRemoved {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ class Unused {
+ [Kept]
+ public int Field1;
+
+ [Kept]
+ private int Field2;
+
+ [Kept]
+ internal int Field3;
+
+ [Kept]
+ public static int Field4;
+
+ [Kept]
+ private static int Field5;
+
+ [Kept]
+ internal static int Field6;
+
+ public string Property1 { get; set; }
+ private string Property2 { get; set; }
+ internal string Property3 { get; set; }
+ public static string Property4 { get; set; }
+ private static string Property5 { get; set; }
+ internal static string Property6 { get; set; }
+
+ [Kept]
+ public void PreservedMethod ()
+ {
+ }
+
+ public void Method1 ()
+ {
+ }
+
+ private void Method2 ()
+ {
+ }
+
+ internal void Method3 ()
+ {
+ }
+
+ public static void Method4 ()
+ {
+ }
+
+ private static void Method5 ()
+ {
+ }
+
+ internal static void Method6 ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveFieldsHasMethodsRemoved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveFieldsHasMethodsRemoved.xml
new file mode 100644
index 000000000..619a8db26
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveFieldsHasMethodsRemoved.xml
@@ -0,0 +1,7 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypeWithPreserveFieldsHasMethodsRemoved/Unused" preserve="fields">
+ <method signature="System.Void PreservedMethod()" />
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveMethodsHasFieldsRemoved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveMethodsHasFieldsRemoved.cs
new file mode 100644
index 000000000..8a79d2d2b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveMethodsHasFieldsRemoved.cs
@@ -0,0 +1,74 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedTypeWithPreserveMethodsHasFieldsRemoved {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Unused {
+ public int Field1;
+ private int Field2;
+ internal int Field3;
+ public static int Field4;
+ private static int Field5;
+ internal static int Field6;
+
+ [Kept]
+ [KeptBackingField]
+ public string Property1 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ private string Property2 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ internal string Property3 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ public static string Property4 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ private static string Property5 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ [KeptBackingField]
+ internal static string Property6 { [Kept] get; [Kept] set; }
+
+ [Kept]
+ public void Method1 ()
+ {
+ }
+
+ [Kept]
+ private void Method2 ()
+ {
+ }
+
+ [Kept]
+ internal void Method3 ()
+ {
+ }
+
+ [Kept]
+ public static void Method4 ()
+ {
+ }
+
+ [Kept]
+ private static void Method5 ()
+ {
+ }
+
+ [Kept]
+ internal static void Method6 ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveMethodsHasFieldsRemoved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveMethodsHasFieldsRemoved.xml
new file mode 100644
index 000000000..20723f8ed
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveMethodsHasFieldsRemoved.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypeWithPreserveMethodsHasFieldsRemoved/Unused" preserve="methods" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingAndPreserveMembers.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingAndPreserveMembers.cs
new file mode 100644
index 000000000..b9d404f22
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingAndPreserveMembers.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedTypeWithPreserveNothingAndPreserveMembers {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ class Unused {
+ [Kept]
+ public int Field1;
+
+ private int Field2;
+
+ [Kept]
+ public void Method1 ()
+ {
+ }
+
+ private void Method2 ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingAndPreserveMembers.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingAndPreserveMembers.xml
new file mode 100644
index 000000000..d672e9e09
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingAndPreserveMembers.xml
@@ -0,0 +1,8 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypeWithPreserveNothingAndPreserveMembers/Unused" preserve="nothing">
+ <field signature="System.Int32 Field1" />
+ <method signature="System.Void Method1()" />
+ </type>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingHasMembersRemoved.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingHasMembersRemoved.cs
new file mode 100644
index 000000000..d6ea29b89
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingHasMembersRemoved.cs
@@ -0,0 +1,50 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ class UnusedTypeWithPreserveNothingHasMembersRemoved {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ class Unused {
+ public int Field1;
+ private int Field2;
+ internal int Field3;
+ public static int Field4;
+ private static int Field5;
+ internal static int Field6;
+
+ public string Property1 { get; set; }
+ private string Property2 { get; set; }
+ internal string Property3 { get; set; }
+ public static string Property4 { get; set; }
+ private static string Property5 { get; set; }
+ internal static string Property6 { get; set; }
+
+ public void Method1 ()
+ {
+ }
+
+ private void Method2 ()
+ {
+ }
+
+ internal void Method3 ()
+ {
+ }
+
+ public static void Method4 ()
+ {
+ }
+
+ private static void Method5 ()
+ {
+ }
+
+ internal static void Method6 ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingHasMembersRemoved.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingHasMembersRemoved.xml
new file mode 100644
index 000000000..f76df307a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UnusedTypeWithPreserveNothingHasMembersRemoved.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UnusedTypeWithPreserveNothingHasMembersRemoved/Unused" preserve="nothing" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredTypeIsKept.cs b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredTypeIsKept.cs
new file mode 100644
index 000000000..37cce219c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredTypeIsKept.cs
@@ -0,0 +1,52 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.LinkXml {
+ public class UsedNonRequiredTypeIsKept {
+ public static void Main ()
+ {
+ var tmp = typeof (Used1).ToString ();
+ tmp = typeof (Used2).ToString ();
+ tmp = typeof (Used3).ToString ();
+ }
+
+ class Used1 {
+ [Kept]
+ public int field;
+
+ public void Method ()
+ {
+ }
+
+ public int Property { get; set; }
+ }
+
+ [KeptMember (".ctor()")]
+ class Used2 {
+ public int field;
+
+ [Kept]
+ public void Method ()
+ {
+ }
+
+ [Kept]
+ [KeptBackingField]
+ public int Property { [Kept] get; [Kept] set; }
+ }
+
+ [KeptMember (".ctor()")]
+ class Used3 {
+ [Kept]
+ public int field;
+
+ [Kept]
+ public void Method ()
+ {
+ }
+
+ [Kept]
+ [KeptBackingField]
+ public int Property { [Kept] get; [Kept] set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredTypeIsKept.xml b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredTypeIsKept.xml
new file mode 100644
index 000000000..2294c4f4f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/LinkXml/UsedNonRequiredTypeIsKept.xml
@@ -0,0 +1,7 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UsedNonRequiredTypeIsKept/Used1" preserve="fields" required="0"/>
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UsedNonRequiredTypeIsKept/Used2" preserve="methods" required="0"/>
+ <type fullname="Mono.Linker.Tests.Cases.LinkXml.UsedNonRequiredTypeIsKept/Used3" preserve="all" required="0"/>
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj b/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj
new file mode 100644
index 000000000..27c913108
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj
@@ -0,0 +1,621 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{B6BEE6AA-ADA0-4E1D-9A17-FBF2936F82B5}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Mono.Linker.Tests.Cases</RootNamespace>
+ <AssemblyName>Mono.Linker.Tests.Cases</AssemblyName>
+ <TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;INCLUDE_EXPECTATIONS</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>0</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;INCLUDE_EXPECTATIONS</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>0</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Attributes.Debugger\DebuggerDisplayAttributeOnAssemblyUsingTarget.cs" />
+ <Compile Include="Attributes.Debugger\DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs" />
+ <Compile Include="Attributes.Debugger\DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs" />
+ <Compile Include="Attributes.Debugger\DebuggerDisplayAttributeOnType.cs" />
+ <Compile Include="Attributes.Debugger\DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs" />
+ <Compile Include="Attributes.Debugger\DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs" />
+ <Compile Include="Attributes.Debugger\DebuggerTypeProxyAttributeOnType.cs" />
+ <Compile Include="Attributes.Debugger\Dependencies\DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly_Lib.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInSameAssembly.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfGenericTypeInOtherAssembly.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameOfNestedTypeInOtherAssembly.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerDisplayAttributeOnAssemblyUsingTargetTypeNameInOtherAssembly.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerTypeProxyAttributeOnAssemblyUsingTarget.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerDisplayAttributeOnAssemblyUsingTarget.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerDisplayAttributeOnAssemblyUsingTargetOnUnusedType.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerTypeProxyAttributeOnType.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerDisplayAttributeOnType.cs" />
+ <Compile Include="Attributes.Debugger\KeepDebugMembers\DebuggerDisplayAttributeOnTypeThatIsNotUsed.cs" />
+ <Compile Include="Attributes\AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly.cs" />
+ <Compile Include="Attributes\AssemblyAttributeKeptInComplexCase.cs" />
+ <Compile Include="Attributes\AttributeOnAssemblyIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnParameterInUsedMethodIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnPreservedTypeWithTypeUsedInConstructorIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnPreservedTypeWithTypeUsedInDifferentNamespaceIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnPreservedTypeWithTypeUsedInFieldIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnUsedFieldIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnPreservedTypeIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnPreservedTypeWithTypeUsedInPropertySetterIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnPreservedTypeWithUsedSetter.cs" />
+ <Compile Include="Attributes\AttributeOnUsedMethodIsKept.cs" />
+ <Compile Include="Attributes\AttributeOnUsedPropertyIsKept.cs" />
+ <None Include="Attributes\OnlyKeepUsed\Dependencies\UnusedAttributeWithTypeForwarderIsRemoved_Forwarder.cs" />
+ <Compile Include="Attributes\CoreLibraryAssemblyAttributesAreKept.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs" />
+ <Compile Include="Attributes\Csc\OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs" />
+ <Compile Include="Attributes\Dependencies\AttributeDefinedInReference.cs" />
+ <Compile Include="Attributes\Dependencies\TypeDefinedInReference.cs" />
+ <Compile Include="Attributes\Dependencies\TypeDefinedInReference2.cs" />
+ <Compile Include="Attributes\Dependencies\TypeDefinedInReferenceWithReference.cs" />
+ <Compile Include="Attributes\FixedLengthArrayAttributesArePreserved.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeArrayOnAttributeCtorOnType.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssembly.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnAssemblyOtherTypesInAttributeAssemblyUsed.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnEvent.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnMethod.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnProperty.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeCtorOnType.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnAssembly.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnEvent.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnMethod.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnProperty.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributeFieldOnType.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnAssembly.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnEvent.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnMethod.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnProperty.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyIsTypeOnAttributePropertyOnType.cs" />
+ <Compile Include="Attributes\Mcs\OnlyTypeUsedInAssemblyWithReferenceIsTypeOnAttributeCtorOnType.cs" />
+ <Compile Include="Attributes\NoSecurity\SecurityAttributesOnUsedMethodAreRemoved.cs" />
+ <Compile Include="Attributes\NoSecurity\SecurityAttributesOnUsedTypeAreRemoved.cs" />
+ <Compile Include="Attributes\NoSecurity\CoreLibrarySecurityAttributeTypesAreRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\ComAttributesArePreserved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\ComAttributesAreRemovedWhenFeatureExcluded.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\ContextStaticIsPreservedOnField.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\Dependencies\UnusedAttributeWithTypeForwarderIsRemoved_Lib.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\AttributeDefinedAndUsedInOtherAssemblyIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\AttributeUsedByAttributeIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\CoreLibraryUsedAssemblyAttributesAreKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\FixedLengthArrayAttributesArePreserved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\ThreadStaticIsPreservedOnField.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\CoreLibraryUnusedAssemblyAttributesAreRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeOnReturnTypeIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeTypeOnModuleIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeWithTypeForwarderIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\CanLinkCoreLibrariesWithOnlyKeepUsedAttributes.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\Dependencies\AttributeDefinedAndUsedInOtherAssemblyIsKept_Lib.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributePreservedViaLinkXmlIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeTypeOnAssemblyIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeTypeOnEventIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeTypeOnMethodIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeTypeOnParameterIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeTypeOnPropertyIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UnusedAttributeTypeOnTypeIsRemoved.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UsedAttributeTypeOnAssemblyIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UsedAttributeTypeOnEventIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UsedAttributeTypeOnMethodIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UsedAttributeTypeOnModuleIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UsedAttributeTypeOnParameterIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UsedAttributeTypeOnPropertyIsKept.cs" />
+ <Compile Include="Attributes\OnlyKeepUsed\UsedAttributeTypeOnTypeIsKept.cs" />
+ <Compile Include="Attributes\SecurityAttributesOnUsedMethodAreKept.cs" />
+ <Compile Include="Attributes\SecurityAttributesOnUsedTypeAreKept.cs" />
+ <Compile Include="Attributes\Dependencies\AssemblyAttributeIsRemovedIfOnlyTypesUsedInAssembly_Lib.cs" />
+ <Compile Include="Attributes\Dependencies\AssemblyAttributeKeptInComplexCase_Lib.cs" />
+ <Compile Include="Basic\ComplexNestedClassesHasUnusedRemoved.cs" />
+ <Compile Include="Basic\InterfaceMethodImplementedOnBaseClassDoesNotGetStripped.cs" />
+ <Compile Include="Basic\MultiLevelNestedClassesAllRemovedWhenNonUsed.cs" />
+ <Compile Include="Basic\NestedDelegateInvokeMethodsPreserved.cs" />
+ <Compile Include="Basic\InstantiatedTypeWithOverridesFromObject.cs" />
+ <Compile Include="Basic\NeverInstantiatedTypeWithOverridesFromObject.cs" />
+ <Compile Include="Basic\UninvokedInterfaceMemberGetsRemoved.cs" />
+ <Compile Include="Basic\UnusedDelegateGetsRemoved.cs" />
+ <Compile Include="Basic\UnusedEnumGetsRemoved.cs" />
+ <Compile Include="Basic\UnusedEventGetsRemoved.cs" />
+ <Compile Include="Basic\InitializerForArrayIsKept.cs" />
+ <Compile Include="Basic\UnusedFieldsOfStructsAreKept.cs" />
+ <Compile Include="Basic\UsedEnumIsKept.cs" />
+ <Compile Include="Basic\UsedEventOnInterfaceIsKept.cs" />
+ <Compile Include="Basic\UnusedFieldGetsRemoved.cs" />
+ <Compile Include="Basic\UnusedMethodGetsRemoved.cs" />
+ <Compile Include="Basic\UnusedPropertyGetsRemoved.cs" />
+ <Compile Include="Basic\UnusedPropertySetterRemoved.cs" />
+ <Compile Include="Basic\UsedEventIsKept.cs" />
+ <Compile Include="Basic\UsedEventOnInterfaceIsRemovedWhenUsedFromClass.cs" />
+ <Compile Include="Basic\UsedPropertyIsKept.cs" />
+ <Compile Include="Basic\UsedStructIsKept.cs" />
+ <Compile Include="BCLFeatures\ETW\LocalsOfModifiedMethodAreRemoved.cs" />
+ <Compile Include="BCLFeatures\ETW\StubbedMethodWithExceptionHandlers.cs" />
+ <Compile Include="CommandLine\ResponseFilesWork.cs" />
+ <Compile Include="CoreLink\CanIncludeI18nAssemblies.cs" />
+ <Compile Include="CoreLink\DelegateAndMulticastDelegateKeepInstantiatedReqs.cs" />
+ <Compile Include="CoreLink\NeverInstantiatedTypeWithOverridesFromObject.cs" />
+ <Compile Include="CoreLink\NoSecurityPlusOnlyKeepUsedRemovesAllSecurityAttributesFromCoreLibraries.cs" />
+ <Compile Include="CoreLink\InstantiatedTypeWithOverridesFromObject.cs" />
+ <Compile Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\OverrideOfAbstractIsKept.cs" />
+ <Compile Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\OverrideOfVirtualCanBeRemoved.cs" />
+ <Compile Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\OverrideOfVirtualCanBeRemoved2.cs" />
+ <Compile Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\OverrideOfVirtualCanBeRemoved3.cs" />
+ <Compile Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\OverrideThatAlsoFulfilsInterface.cs" />
+ <Compile Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.cs" />
+ <Compile Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.cs" />
+ <Compile Include="Inheritance.AbstractClasses\UnusedAbstractMethodRemoved.cs" />
+ <Compile Include="Inheritance.AbstractClasses\UnusedVirtualMethodRemoved.cs" />
+ <Compile Include="Inheritance.AbstractClasses\UsedOverrideOfAbstractMethodIsKept.cs" />
+ <Compile Include="Inheritance.AbstractClasses\UsedOverrideOfVirtualMethodIsKept.cs" />
+ <Compile Include="Inheritance.Interfaces\Dependencies\InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Copy.cs" />
+ <Compile Include="Inheritance.Interfaces\Dependencies\InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit_Link.cs" />
+ <Compile Include="Inheritance.Interfaces\Dependencies\InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Copy.cs" />
+ <Compile Include="Inheritance.Interfaces\Dependencies\InterfaceTypeInOtherUsedOnlyByCopiedAssembly_Link.cs" />
+ <Compile Include="Inheritance.Interfaces\Dependencies\InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed_Lib.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassImplementingInterfaceMethodsNested.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassImplementingInterfaceMethodsNested2.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassImplemtingInterfaceMethodsThroughBaseClass2.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassImplemtingInterfaceMethodsThroughBaseClass3.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassImplemtingInterfaceMethodsThroughBaseClass4.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassImplemtingInterfaceMethodsThroughBaseClass5.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassImplemtingInterfaceMethodsThroughBaseClass6.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassUsedFromConcreteTypeHasInterfaceMethodRemoved.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ClassUsedFromInterfaceHasInterfaceMethodKept.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\InterfaceMarkOrderingDoesNotMatter.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\InterfaceMarkOrderingDoesNotMatter2.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\InterfaceMarkOrderingDoesNotMatter3.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\InterfaceTypeInOtherUsedOnlyByCopiedAssembly.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\InterfaceTypeInOtherUsedOnlyByCopiedAssemblyExplicit.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\InterfaceUsedOnlyAsConstraintIsKept.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\InterfaceWithInterfaceFromOtherAssemblyWhenExplicitMethodUsed.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\InterfaceTypeOnlyUsedHasInterfacesRemoved.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndAssemblyPreserveAll.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveAll.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveFields.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveMethods.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveNone.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\ArrayWithIndexAssignedToReturnValue.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\ArrayPassedAsParameter.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\FieldDowncastedToInterface.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\GenericType.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\GenericTypeWithConstraint2.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\GenericTypeWithConstraint3.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\InterfaceOnMultipleBases.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\LocalDowncastedToInterface.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\LocalPassedAsParameter.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\LocalPassedAsParameterToGeneric.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\LocalPassedAsParameterToGenericWithConstraint.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\LocalPassedAsParameterToGenericWithConstraint2.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\ReturnValueDowncastedToInterface.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtorButInterfaceNeeded\GenericTypeWithConstraint.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\ComInterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\ExplicitInterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\GenericType.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\InterfaceFromCopiedAssemblyCanBeRemoved.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\LocalDowncastDoesNotCuaseOtherTypesToKeepInterface.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\GenericWithConstraintDoesNotCauseOtherTypesToKeepInterface.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\ObjectHardCastedToInterface.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\PreserveDependencyPreservesInterfaceMethod.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeWithPreserveFields.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeWithPreserveMethods.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeHasInterfaceMethodPreservedViaXml.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ObjectCastedToSecondInterfaceHasMemberRemovedButInterfaceKept.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\ExplicitInterfaceMethodWhichCreatesInstanceOfParentType.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\TypeGetsMarkedThatImplementsAlreadyMarkedInterfaceMethod.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\UnusedComInterfaceIsKept.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\UnusedComInterfaceIsRemovedWhenComFeatureExcluded.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\UnusedExplicitInterfaceHasMethodPreservedViaXml.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\UnusedExplicitInterfaceIsRemoved.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\UnusedInterfaceHasMethodPreservedViaXml.cs" />
+ <Compile Include="Inheritance.Interfaces\OnReferenceType\UnusedInterfaceTypeIsRemoved.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\NoKeptCtor\InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsed.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\NoKeptCtor\InterfaceCanBeRemovedFromClassWithOnlyStaticMethodUsedWithCctor.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\NoKeptCtor\InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethod.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\NoKeptCtor\InterfaceTypeRemovedWhenOnlyUsedByClassWithOnlyStaticMethodMultiple.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\StructImplementingInterfaceMethodsNested.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\StructImplementingInterfaceMethodsNested2.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\StructUsedFromConcreteTypeHasInterfaceMethodRemoved.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\StructUsedFromConcreteTypeHasInterfaceMethodRemoved2.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\StructUsedFromInterfaceHasInterfaceMethodKept.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\UnusedExplicitInterfaceHasMethodPreservedViaXml.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\UnusedExplicitInterfaceIsRemoved.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\UnusedInterfaceHasMethodPreservedViaXml.cs" />
+ <Compile Include="Inheritance.Interfaces\OnValueType\UnusedInterfaceTypeIsRemoved.cs" />
+ <Compile Include="Inheritance.VirtualMethods\HarderToDetectUnusedVirtualMethodGetsRemoved.cs" />
+ <Compile Include="Inheritance.VirtualMethods\UnusedTypeWithOverrideOfVirtualMethodIsRemoved.cs" />
+ <Compile Include="Inheritance.VirtualMethods\UnusedVirtualMethodRemoved.cs" />
+ <Compile Include="Inheritance.VirtualMethods\UsedOverrideOfVirtualMethodIsKept.cs" />
+ <Compile Include="Inheritance.VirtualMethods\UsedTypeWithOverrideOfVirtualMethodHasOverrideKept.cs" />
+ <Compile Include="Inheritance.VirtualMethods\VirtualMethodGetsPerservedIfBaseMethodGetsInvoked.cs" />
+ <Compile Include="Inheritance.VirtualMethods\VirtualMethodGetsStrippedIfImplementingMethodGetsInvokedDirectly.cs" />
+ <Compile Include="Libraries\CanLinkPublicApisOfLibrary.cs" />
+ <Compile Include="Libraries\DefaultLibraryLinkBehavior.cs" />
+ <Compile Include="Libraries\Dependencies\UserAssemblyActionWorks_Lib.cs" />
+ <Compile Include="Libraries\UserAssemblyActionWorks.cs" />
+ <Compile Include="LinkXml\AssemblyWithPreserveAll.cs" />
+ <Compile Include="LinkXml\CanPreserveTypesUsingRegex.cs" />
+ <Compile Include="LinkXml\CanPreserveAnExportedType.cs" />
+ <None Include="LinkXml\Dependencies\CanPreserveAnExportedType_Forwarder.cs" />
+ <Compile Include="LinkXml\CanPreserveExportedTypesUsingRegex.cs" />
+ <Compile Include="LinkXml\Dependencies\CanPreserveAnExportedType_Library.cs" />
+ <Compile Include="LinkXml\Dependencies\EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod\Base.cs" />
+ <Compile Include="LinkXml\Dependencies\EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod\Library1.cs" />
+ <Compile Include="LinkXml\Dependencies\EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod\Library2.cs" />
+ <Compile Include="LinkXml\EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod.cs" />
+ <Compile Include="LinkXml\FeatureExclude\OnAssembly.cs" />
+ <Compile Include="LinkXml\FeatureExclude\OnEvent.cs" />
+ <Compile Include="LinkXml\FeatureExclude\OnField.cs" />
+ <Compile Include="LinkXml\FeatureExclude\OnMethod.cs" />
+ <Compile Include="LinkXml\FeatureExclude\OnProperty.cs" />
+ <Compile Include="LinkXml\FeatureExclude\OnType.cs" />
+ <Compile Include="LinkXml\FeatureExclude\Dependencies\OnAssembly_Lib1.cs" />
+ <Compile Include="LinkXml\FeatureExclude\Dependencies\OnAssembly_Lib2.cs" />
+ <Compile Include="LinkXml\UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.cs" />
+ <Compile Include="LinkXml\UnusedEventPreservedByLinkXmlIsKept.cs" />
+ <Compile Include="LinkXml\UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.cs" />
+ <Compile Include="LinkXml\UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.cs" />
+ <Compile Include="LinkXml\UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.cs" />
+ <Compile Include="LinkXml\UnusedNonRequiredTypeIsRemoved.cs" />
+ <Compile Include="LinkXml\UnusedTypePreservedByLinkXmlWithCommentIsKept.cs" />
+ <Compile Include="LinkXml\UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.cs" />
+ <Compile Include="LinkXml\UsedNonRequiredTypeIsKept.cs" />
+ <Compile Include="PreserveDependencies\Dependencies\PreserveDependencyMethodInAssemblyLibrary.cs" />
+ <Compile Include="PreserveDependencies\Dependencies\PreserveDependencyMethodInNonReferencedAssemblyBase.cs" />
+ <Compile Include="PreserveDependencies\Dependencies\PreserveDependencyMethodInNonReferencedAssemblyBase2.cs" />
+ <Compile Include="PreserveDependencies\Dependencies\PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary.cs" />
+ <Compile Include="PreserveDependencies\Dependencies\PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary.cs" />
+ <Compile Include="PreserveDependencies\Dependencies\PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs" />
+ <Compile Include="PreserveDependencies\Dependencies\PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction_Lib.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyField.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyMethod.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyMethodInAssembly.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyMethodInNonReferencedAssembly.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyMethodInNonReferencedAssemblyChained.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyMethodInNonReferencedAssemblyChainedReference.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyMethodInNonReferencedAssemblyWithEmbeddedXml.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyOnUnusedMethodInNonReferencedAssembly.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction.cs" />
+ <Compile Include="PreserveDependencies\PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithEmbeddedXml.cs" />
+ <Compile Include="References\AssemblyOnlyUsedByUsingWithCsc.cs" />
+ <Compile Include="References\AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs" />
+ <Compile Include="References\AssemblyOnlyUsedByUsingWithMcs.cs" />
+ <Compile Include="References\Dependencies\AssemblyOnlyUsedByUsing_Copied.cs" />
+ <Compile Include="References\Dependencies\AssemblyOnlyUsedByUsing_Lib.cs" />
+ <Compile Include="References\Individual\CanSkipUnresolved.cs" />
+ <Compile Include="References\Individual\Dependencies\CanSkipUnresolved_Library.cs" />
+ <Compile Include="References\Dependencies\UserAssembliesAreLinkedByDefault_Library1.cs" />
+ <Compile Include="References\UserAssembliesAreLinkedByDefault.cs" />
+ <Compile Include="Reflection\AssemblyImportedViaReflectionWithDerivedType.cs" />
+ <Compile Include="Reflection\AssemblyImportedViaReflectionWithReference.cs" />
+ <Compile Include="Reflection\ConstructorUsedViaReflection.cs" />
+ <Compile Include="Reflection\Dependencies\AssemblyDependencyWithReference.cs" />
+ <Compile Include="Reflection\Dependencies\AssemblyImportedViaReflectionWithDerivedType_Base.cs" />
+ <Compile Include="Reflection\Dependencies\AssemblyImportedViaReflectionWithDerivedType_Reflect.cs" />
+ <Compile Include="Reflection\EventUsedViaReflection.cs" />
+ <Compile Include="Reflection\FieldUsedViaReflection.cs" />
+ <Compile Include="Reflection\MethodUsedViaReflectionWithDefaultBindingFlags.cs" />
+ <Compile Include="Reflection\MightKeepExtraThings.cs" />
+ <Compile Include="Reflection\MethodUsedViaReflection.cs" />
+ <Compile Include="Reflection\PropertyUsedViaReflection.cs" />
+ <Compile Include="Reflection\TypeUsedViaReflection.cs" />
+ <Compile Include="Reflection\TypeUsedViaReflectionAssemblyDoesntExist.cs" />
+ <Compile Include="Reflection\TypeUsedViaReflectionInDifferentAssembly.cs" />
+ <Compile Include="Reflection\TypeUsedViaReflectionLdstrIncomplete.cs" />
+ <Compile Include="Reflection\TypeUsedViaReflectionLdstrValidButChanged.cs" />
+ <Compile Include="Reflection\TypeUsedViaReflectionTypeDoesntExist.cs" />
+ <Compile Include="Reflection\TypeUsedViaReflectionTypeNameIsSymbol.cs" />
+ <Compile Include="Reflection\UsedViaReflectionIntegrationTest.cs" />
+ <Compile Include="Resources\EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly.cs" />
+ <Compile Include="Resources\Dependencies\EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1.cs" />
+ <Compile Include="Resources\EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy.cs" />
+ <Compile Include="Resources\Dependencies\EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.cs" />
+ <Compile Include="Resources\EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink.cs" />
+ <Compile Include="Resources\Dependencies\EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.cs" />
+ <Compile Include="Resources\EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs" />
+ <Compile Include="Resources\EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.cs" />
+ <Compile Include="Resources\EmbeddedLinkXmlFileIsProcessed.cs" />
+ <Compile Include="Resources\EmbeddedLinkXmlFileIsProcessedAndKept.cs" />
+ <Compile Include="Resources\NonLinkerEmbeddedResourceHasNoImpact.cs" />
+ <Compile Include="Statics\DisableBeforeFieldInit\UnusedStaticFieldInitializer.cs" />
+ <Compile Include="Symbols\Dependencies\LibraryWithEmbeddedPdbSymbols.cs" />
+ <Compile Include="Symbols\Dependencies\LibraryWithPortablePdbSymbols.cs" />
+ <Compile Include="Symbols\ReferenceWithEmbeddedPdb.cs" />
+ <Compile Include="Symbols\ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithEmbeddedPdbCopyAction.cs" />
+ <Compile Include="Symbols\ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithEmbeddedPdbDeleteAction.cs" />
+ <Compile Include="Symbols\ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithMdbCopyAction.cs" />
+ <Compile Include="Symbols\ReferenceWithMdbCopyActionAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithMdbDeleteAction.cs" />
+ <Compile Include="Symbols\ReferenceWithMdbDeleteActionAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithPdb.cs" />
+ <Compile Include="Symbols\ReferenceWithPdbAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\AssemblyWithDefaultSymbolsAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\AssemblyWithDefaultSymbols.cs" />
+ <Compile Include="Symbols\Dependencies\LibraryWithCompilerDefaultSymbols.cs" />
+ <Compile Include="Symbols\Dependencies\LibraryWithPdb\LibraryWithPdb.cs" />
+ <Compile Include="Symbols\Dependencies\LibraryWithMdb\LibraryWithMdb.cs" />
+ <Compile Include="Symbols\ReferenceWithPdbCopyAction.cs" />
+ <Compile Include="Symbols\ReferenceWithPdbCopyActionAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithPdbDeleteAction.cs" />
+ <Compile Include="Symbols\ReferenceWithPdbDeleteActionAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithPortablePdb.cs" />
+ <Compile Include="Symbols\ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithPortablePdbCopyAction.cs" />
+ <Compile Include="Symbols\ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithPortablePdbDeleteAction.cs" />
+ <Compile Include="Symbols\ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs" />
+ <Compile Include="TestFramework\CanCheckInitializersByIndex.cs" />
+ <Compile Include="TestFramework\CanCompileILAssembly.cs" />
+ <Compile Include="TestFramework\CanCompileReferencesUsingTypes.cs" />
+ <Compile Include="TestFramework\CanCompileReferencesWithResources.cs" />
+ <Compile Include="TestFramework\CanCompileReferencesWithResourcesWithCsc.cs" />
+ <Compile Include="TestFramework\CanCompileReferencesWithResourcesWithMcs.cs" />
+ <Compile Include="TestFramework\CanCompileTestCaseWithDebugPdbs.cs" />
+ <Compile Include="TestFramework\CanCompileTestCaseWithCsc.cs" />
+ <Compile Include="TestFramework\CanCompileTestCaseWithMsc.cs" />
+ <Compile Include="TestFramework\CanSandboxDependenciesUsingType.cs" />
+ <Compile Include="TestFramework\CanVerifyInterfacesOnTypesInAssembly.cs" />
+ <Compile Include="TestFramework\Dependencies\CanCompileReferencesUsingTypes_LibSource1.cs" />
+ <Compile Include="TestFramework\Dependencies\CanCompileReferencesUsingTypes_LibSource2.cs" />
+ <Compile Include="TestFramework\Dependencies\CanCompileReferencesWithResources_Lib1.cs" />
+ <Compile Include="TestFramework\Dependencies\CanCompileTestCaseWithCsc_Lib.cs" />
+ <Compile Include="TestFramework\Dependencies\CanCompileTestCaseWithMcs_Lib.cs" />
+ <Compile Include="TestFramework\Dependencies\CanSandboxDependenciesUsingType_Source1.cs" />
+ <Compile Include="TestFramework\Dependencies\CanSandboxDependenciesUsingType_Source2.cs" />
+ <Compile Include="TestFramework\Dependencies\CanVerifyInterfacesOnTypesInAssembly_Lib.cs" />
+ <Compile Include="TestFramework\Dependencies\VerifyAttributesInAssemblyWorks_Base.cs" />
+ <Compile Include="TestFramework\Dependencies\VerifyAttributesInAssemblyWorks_Lib.cs" />
+ <Compile Include="TestFramework\VerifyAttributesInAssemblyWorks.cs" />
+ <Compile Include="TestFramework\VerifyAttributesInAssemblyWorksWithStrings.cs" />
+ <Compile Include="TestFramework\VerifyDefineAttributeBehavior.cs" />
+ <None Include="TypeForwarding\Dependencies\ForwarderLibrary.cs" />
+ <Compile Include="TestFramework\VerifyExpectModifiedAttributesWork.cs" />
+ <Compile Include="TestFramework\VerifyResourceInAssemblyAttributesBehavior.cs" />
+ <Compile Include="Tracing\Individual\CanDumpDependenciesToUncompressedXml.cs" />
+ <Compile Include="Tracing\Individual\CanEnableDependenciesDump.cs" />
+ <Compile Include="Tracing\Individual\CanEnableReducedTracing.cs" />
+ <Compile Include="TypeForwarding\Dependencies\ImplementationLibrary.cs" />
+ <Compile Include="TypeForwarding\Dependencies\LibraryUsingForwarder.cs" />
+ <Compile Include="TypeForwarding\Dependencies\ReferenceImplementationLibrary.cs" />
+ <Compile Include="TypeForwarding\TypeForwarderOnlyAssembliesRemoved.cs" />
+ <Compile Include="TypeForwarding\TypeForwarderOnlyAssembliesKept.cs" />
+ <Compile Include="TypeForwarding\TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.cs" />
+ <Compile Include="CoreLink\CopyOfCoreLibrariesKeepsUnusedTypes.cs" />
+ <Compile Include="CoreLink\LinkingOfCoreLibrariesRemovesUnusedMethods.cs" />
+ <Compile Include="CoreLink\LinkingOfCoreLibrariesRemovesUnusedTypes.cs" />
+ <Compile Include="Advanced\DeadCodeElimination1.cs" />
+ <Compile Include="Advanced\FieldThatOnlyGetsSetIsRemoved.cs" />
+ <Compile Include="Generics\CorrectOverloadedMethodGetsStrippedInGenericClass.cs" />
+ <Compile Include="Generics\DerivedClassWithMethodOfSameNameAsBaseButDifferentNumberOfGenericParametersUnusedBaseWillGetStripped.cs" />
+ <Compile Include="Generics\GenericInstanceInterfaceMethodImplementedWithDifferentGenericArgumentNameDoesNotGetStripped.cs" />
+ <Compile Include="Generics\MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameter.cs" />
+ <Compile Include="Generics\MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase.cs" />
+ <Compile Include="Generics\MethodWithParameterWhichHasGenericParametersAndOverrideUsesADifferentNameForGenericParameterNestedCase2.cs" />
+ <Compile Include="Generics\OverrideWithAnotherVirtualMethodOfSameNameWithDifferentParameterType.cs" />
+ <Compile Include="Interop\InternalCalls\Com\DefaultConstructorOfParameterIsRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\Com\FieldsOfParameterAreRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\Com\FieldsOfReturnTypeAreRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\Com\FieldsOfThisAreRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\DefaultConstructorOfReturnTypeIsNotRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\Com\DefaultConstructorOfReturnTypeIsRemoved.cs" />
+ <Compile Include="Interop\PInvoke\Com\DefaultConstructorOfParameterIsRemoved.cs" />
+ <Compile Include="Interop\PInvoke\Com\DefaultConstructorOfReturnTypeIsRemoved.cs" />
+ <Compile Include="Interop\PInvoke\Com\FieldsOfParameterAreRemoved.cs" />
+ <Compile Include="Interop\PInvoke\Com\FieldsOfReturnTypeAreRemoved.cs" />
+ <Compile Include="Interop\PInvoke\Com\FieldsOfThisAreRemoved.cs" />
+ <Compile Include="Interop\PInvoke\DefaultConstructorOfReturnTypeIsNotRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs" />
+ <Compile Include="Interop\PInvoke\UnusedDefaultConstructorOfTypePassedByRefIsNotRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\UnusedDefaultConstructorIsRemoved.cs" />
+ <Compile Include="Interop\PInvoke\UnusedDefaultConstructorIsRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\UnusedFieldsOfTypesAreNotRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs" />
+ <Compile Include="Interop\PInvoke\UnusedFieldsOfTypesAreNotRemoved.cs" />
+ <Compile Include="Interop\PInvoke\UnusedFieldsOfTypesPassedByRefAreNotRemoved.cs" />
+ <Compile Include="Interop\InternalCalls\UnusedFieldsOfTypesWhenHasThisAreNotRemoved.cs" />
+ <Compile Include="LinkXml\TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.cs" />
+ <Compile Include="LinkXml\UnusedFieldPreservedByLinkXmlIsKept.cs" />
+ <Compile Include="LinkXml\UnusedMethodPreservedByLinkXmlIsKept.cs" />
+ <Compile Include="LinkXml\UnusedNestedTypePreservedByLinkXmlIsKept.cs" />
+ <Compile Include="LinkXml\UnusedPropertyPreservedByLinkXmlIsKept.cs" />
+ <Compile Include="LinkXml\UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.cs" />
+ <Compile Include="LinkXml\UnusedTypePreservedByLinkXmlIsKept.cs" />
+ <Compile Include="LinkXml\UnusedTypeWithPreserveAllHasAllMembersPreserved.cs" />
+ <Compile Include="LinkXml\UnusedTypeWithPreserveFieldsHasMethodsRemoved.cs" />
+ <Compile Include="LinkXml\UnusedTypeWithPreserveMethodsHasFieldsRemoved.cs" />
+ <Compile Include="LinkXml\UnusedTypeWithPreserveNothingAndPreserveMembers.cs" />
+ <Compile Include="LinkXml\UnusedTypeWithPreserveNothingHasMembersRemoved.cs" />
+ <Compile Include="References\ReferencesAreRemovedWhenAllUsagesAreRemoved.cs" />
+ <Compile Include="Basic\UnusedClassGetsRemoved.cs" />
+ <Compile Include="Basic\UnusedNestedClassGetsRemoved.cs" />
+ <Compile Include="Statics\UnusedStaticMethodGetsRemoved.cs" />
+ <Compile Include="Generics\UsedOverloadedGenericMethodInGenericClassIsNotStripped.cs" />
+ <Compile Include="Generics\UsedOverloadedGenericMethodInstanceInGenericClassIsNotStripped.cs" />
+ <Compile Include="Generics\UsedOverloadedGenericMethodWithNoParametersIsNotStripped.cs" />
+ <Compile Include="Statics\UnusedStaticConstructorGetsRemoved.cs" />
+ <Compile Include="TypeForwarding\MissingTargetReference.cs" />
+ <None Include="TypeForwarding\Dependencies\TypeForwarderMissingReference.il" />
+ <Compile Include="Basic\UsedInterfaceIsKept.cs" />
+ <Compile Include="LinkXml\PreserveBackingFieldWhenPropertyIsKept.cs" />
+ <Compile Include="Symbols\ReferencesWithMixedSymbolTypes.cs" />
+ <Compile Include="Symbols\ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Symbols\ReferenceWithMdb.cs" />
+ <Compile Include="Symbols\ReferenceWithMdbAndSymbolLinkingEnabled.cs" />
+ <Compile Include="Attributes.StructLayout\SequentialClass.cs" />
+ <Compile Include="Attributes.StructLayout\AutoClass.cs" />
+ <Compile Include="Attributes.StructLayout\UnusedTypeWithSequentialLayoutIsRemoved.cs" />
+ <Compile Include="Attributes.StructLayout\ExplicitClass.cs" />
+ <Compile Include="Reflection\AssemblyImportedViaReflection.cs" />
+ <Compile Include="Reflection\Dependencies\AssemblyDependency.cs" />
+ <Compile Include="Statics\ExplicitStaticCtor.cs" />
+ <Compile Include="Statics\UnusedStaticFieldInitializer.cs" />
+ <Compile Include="Statics\StaticFieldInitializer.cs" />
+ <Compile Include="Statics\MixedStaticFieldInitializerAndCtor.cs" />
+ <Compile Include="LinkXml\UnusedTypeDeclarationPreservedByLinkXmlIsKept.cs" />
+ <Compile Include="LinkXml\CanPreserveExcludedFeatureCom.cs" />
+ <Compile Include="BCLFeatures\ETW\CustomEventSource.cs" />
+ <Compile Include="BCLFeatures\ETW\Excluded.cs" />
+ <Compile Include="BCLFeatures\ETW\BaseRemovedEventSource.cs" />
+ <Compile Include="Generics\NewConstraintOnClass.cs" />
+ <Compile Include="BCLFeatures\ETW\NonEventWithLog.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Attributes\OnlyKeepUsed\Dependencies\AssemblyWithUnusedAttributeOnReturnParameterDefinition.il" />
+ <Content Include="Attributes\OnlyKeepUsed\UnusedAttributePreservedViaLinkXmlIsKept.xml" />
+ <Content Include="CommandLine\Dependencies\ResponseFilesWork.rsp" />
+ <Content Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved.xml" />
+ <Content Include="Inheritance.AbstractClasses\NoKeptCtor\OverrideRemoval\PreservesOverriddenMethodOverrideOfUsedVirtualStillRemoved2.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeHasExplicitInterfaceMethodPreservedViaXml.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeHasExplicitInterfacePropertyPreservedViaXml.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeHasInterfaceMethodPreservedViaXml.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\UnusedExplicitInterfaceHasMethodPreservedViaXml.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\Dependencies\NoInstanceCtorAndAssemblyPreserveAll_Lib.il" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndAssemblyPreserveAll.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveAll.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveFields.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveFieldsWithInterfacesMarked.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveMethods.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveMethodsWithInterfacesMarked.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoInstanceCtor\NoInstanceCtorAndTypePreserveNone.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\InterfaceMarkOrderingDoesNotMatter.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\InterfaceMarkOrderingDoesNotMatter2.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\InterfaceMarkOrderingDoesNotMatter3.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeWithPreserveFields.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeWithPreserveMethods.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\NoKeptCtor\UnusedTypeWithPreserveMethodsAndInterfaceTypeMarked.xml" />
+ <Content Include="Inheritance.Interfaces\OnReferenceType\UnusedInterfaceHasMethodPreservedViaXml.xml" />
+ <Content Include="Inheritance.Interfaces\OnValueType\UnusedExplicitInterfaceHasMethodPreservedViaXml.xml" />
+ <Content Include="Inheritance.Interfaces\OnValueType\UnusedInterfaceHasMethodPreservedViaXml.xml" />
+ <Content Include="LinkXml\AssemblyWithPreserveAll.xml" />
+ <Content Include="LinkXml\CanPreserveTypesUsingRegex.xml" />
+ <Content Include="LinkXml\CanPreserveAnExportedType.xml" />
+ <Content Include="LinkXml\CanPreserveExportedTypesUsingRegex.xml" />
+ <Content Include="LinkXml\Dependencies\EmbeddedLinkXmlPreservesAdditionalAssemblyWithOverriddenMethod\Library1.xml" />
+ <Content Include="LinkXml\FeatureExclude\OnAssembly.xml" />
+ <Content Include="LinkXml\FeatureExclude\OnEvent.xml" />
+ <Content Include="LinkXml\FeatureExclude\OnField.xml" />
+ <Content Include="LinkXml\FeatureExclude\OnMethod.xml" />
+ <Content Include="LinkXml\FeatureExclude\OnProperty.xml" />
+ <Content Include="LinkXml\FeatureExclude\OnType.xml" />
+ <Content Include="LinkXml\TypeWithPreserveFieldsHasBackingFieldsOfPropertiesRemoved.xml" />
+ <Content Include="LinkXml\UnusedAssemblyWithNoDefinedPreserveHasAllTypesPreserved.xml" />
+ <Content Include="LinkXml\UnusedEventPreservedByLinkXmlIsKept.xml" />
+ <Content Include="LinkXml\UnusedFieldPreservedByLinkXmlIsKept.xml" />
+ <Content Include="LinkXml\UnusedGenericTypeWithPreserveAllHasAllMembersPreserved.xml" />
+ <Content Include="LinkXml\UnusedInterfaceTypeOnTypeWithPreserveAllIsKept.xml" />
+ <Content Include="LinkXml\UnusedInterfaceTypeOnTypeWithPreserveNothingIsRemoved.xml" />
+ <Content Include="LinkXml\UnusedMethodPreservedByLinkXmlIsKept.xml" />
+ <Content Include="LinkXml\UnusedNestedTypePreservedByLinkXmlIsKept.xml" />
+ <Content Include="LinkXml\UnusedNonRequiredTypeIsRemoved.xml" />
+ <Content Include="LinkXml\UnusedPropertyPreservedByLinkXmlIsKept.xml" />
+ <Content Include="LinkXml\UnusedTypeIsPresservedWhenEntireAssemblyIsPreserved.xml" />
+ <Content Include="LinkXml\UnusedTypePreservedByLinkXmlIsKept.xml" />
+ <Content Include="LinkXml\UnusedTypePreservedByLinkXmlWithCommentIsKept.xml" />
+ <Content Include="LinkXml\UnusedTypeWithNoDefinedPreserveHasAllMembersPreserved.xml" />
+ <Content Include="LinkXml\UnusedTypeWithPreserveAllHasAllMembersPreserved.xml" />
+ <Content Include="LinkXml\UnusedTypeWithPreserveFieldsHasMethodsRemoved.xml" />
+ <Content Include="LinkXml\UnusedTypeWithPreserveMethodsHasFieldsRemoved.xml" />
+ <Content Include="LinkXml\UnusedTypeWithPreserveNothingAndPreserveMembers.xml" />
+ <Content Include="LinkXml\UnusedTypeWithPreserveNothingHasMembersRemoved.xml" />
+ <Content Include="LinkXml\UsedNonRequiredTypeIsKept.xml" />
+ <Content Include="PreserveDependencies\Dependencies\PreserveDependencyMethodInNonReferencedAssemblyLibrary.xml" />
+ <Content Include="Resources\Dependencies\EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1_NotMatchingName.xml" />
+ <Content Include="Resources\Dependencies\EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.xml" />
+ <Content Include="Resources\Dependencies\EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.xml" />
+ <Content Include="Resources\Dependencies\EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.xml" />
+ <Content Include="Resources\Dependencies\EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.xml" />
+ <Content Include="Resources\Dependencies\EmbeddedLinkXmlFileIsProcessed.xml" />
+ <Content Include="Resources\Dependencies\EmbeddedLinkXmlFileIsProcessedAndKept.xml" />
+ <Content Include="Resources\Dependencies\NonLinkerEmbeddedResourceHasNoImpact.xml" />
+ <Content Include="TestFramework\Dependencies\CanCompileReferencesWithResources_Lib1.txt" />
+ <Content Include="TestFramework\Dependencies\CanCompileReferencesWithResources_Lib1.log" />
+ <Content Include="TestFramework\Dependencies\CanCompileTestCaseWithCsc.txt" />
+ <Content Include="TestFramework\Dependencies\CanCompileTestCaseWithMcs.txt" />
+ <Content Include="TestFramework\Dependencies\VerifyResourceInAssemblyAttributesBehavior.txt" />
+ <Content Include="LinkXml\PreserveBackingFieldWhenPropertyIsKept.xml" />
+ <Content Include="TypeForwarding\TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.xml" />
+ <Content Include="LinkXml\UnusedTypeDeclarationPreservedByLinkXmlIsKept.xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Mono.Linker.Tests.Cases.Expectations\Mono.Linker.Tests.Cases.Expectations.csproj">
+ <Project>{2C26601F-3E2F-45B9-A02F-58EE9296E19E}</Project>
+ <Name>Mono.Linker.Tests.Cases.Expectations</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="TestFramework\Dependencies\ILAssemblySample.il" />
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Attributes.StructLayout\" />
+ <Folder Include="Inheritance.Complex" />
+ <Folder Include="Reflection\Dependencies\" />
+ <Folder Include="BCLFeatures\" />
+ <Folder Include="BCLFeatures\ETW\" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="LinkXml\CanPreserveExcludedFeatureCom.xml" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInAssemblyLibrary.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInAssemblyLibrary.cs
new file mode 100644
index 000000000..e67672f38
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInAssemblyLibrary.cs
@@ -0,0 +1,8 @@
+using System;
+namespace Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies {
+ public class PreserveDependencyMethodInAssemblyLibrary {
+ public PreserveDependencyMethodInAssemblyLibrary ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs
new file mode 100644
index 000000000..b64962a85
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs
@@ -0,0 +1,5 @@
+namespace Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies {
+ public abstract class PreserveDependencyMethodInNonReferencedAssemblyBase {
+ public abstract string Method ();
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase2.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase2.cs
new file mode 100644
index 000000000..d5f7883ad
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase2.cs
@@ -0,0 +1,8 @@
+namespace Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies {
+ public class PreserveDependencyMethodInNonReferencedAssemblyBase2 : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ public override string Method ()
+ {
+ return "Base2";
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary.cs
new file mode 100644
index 000000000..6909b63d9
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary.cs
@@ -0,0 +1,16 @@
+using System.Runtime.CompilerServices;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies {
+ public class PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ public override string Method ()
+ {
+ Dependency ();
+ return "Dependency";
+ }
+
+ [PreserveDependency (".ctor()", "Mono.Linker.Tests.Cases.Advanced.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyBase2", "base2")]
+ public static void Dependency ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary.cs
new file mode 100644
index 000000000..6a796ada6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary.cs
@@ -0,0 +1,9 @@
+namespace Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies {
+ public class PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ public override string Method ()
+ {
+ PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary.Dependency ();
+ return "Dependency";
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs
new file mode 100644
index 000000000..57b5bc788
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs
@@ -0,0 +1,12 @@
+namespace Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies {
+ public class PreserveDependencyMethodInNonReferencedAssemblyLibrary : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ public override string Method ()
+ {
+ return "Dependency";
+ }
+
+ private void UnusedMethod ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.xml b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.xml
new file mode 100644
index 000000000..732b24680
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="PreserveDependencyMethodInNonReferencedAssemblyLibrary, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyLibrary" preserve="all" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction_Lib.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction_Lib.cs
new file mode 100644
index 000000000..222887fbc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/Dependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction_Lib.cs
@@ -0,0 +1,7 @@
+namespace Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies {
+ public class PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction_Lib {
+ public static void MethodPreservedViaDependencyAttribute ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyField.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyField.cs
new file mode 100644
index 000000000..8ce9e5ef8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyField.cs
@@ -0,0 +1,24 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ public class PreserveDependencyField {
+ public static void Main ()
+ {
+ var b = new B ();
+ b.field = 3;
+ }
+
+ [KeptMember (".ctor()")]
+ class B {
+ [Kept]
+ [PreserveDependency ("ExtraMethod1")]
+ public int field;
+
+ [Kept]
+ static void ExtraMethod1 ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethod.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethod.cs
new file mode 100644
index 000000000..fc634f0a6
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethod.cs
@@ -0,0 +1,94 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ class PreserveDependencyMethod {
+ public static void Main ()
+ {
+ B.Method ();
+ B.SameContext ();
+ B.Broken ();
+ B.Conditional ();
+ }
+
+ class B
+ {
+ [Kept]
+ int field;
+
+ [Kept]
+ void Method2 (out sbyte arg)
+ {
+ arg = 1;
+ }
+
+ [Kept]
+ [PreserveDependency ("Dependency1()", "Mono.Linker.Tests.Cases.PreserveDependencies.C")]
+ [PreserveDependency ("Dependency2`1 ( T[] , System.Int32 ) ", "Mono.Linker.Tests.Cases.PreserveDependencies.C")]
+ [PreserveDependency ("field", "Mono.Linker.Tests.Cases.PreserveDependencies.C")]
+ [PreserveDependency ("NextOne (Mono.Linker.Tests.Cases.PreserveDependencies.PreserveDependencyMethod+Nested&)", "Mono.Linker.Tests.Cases.PreserveDependencies.PreserveDependencyMethod+Nested")]
+ [PreserveDependency ("Property", "Mono.Linker.Tests.Cases.PreserveDependencies.C")]
+ [PreserveDependency ("get_Property()", "Mono.Linker.Tests.Cases.PreserveDependencies.C")]
+ public static void Method ()
+ {
+ }
+
+ [Kept]
+ [PreserveDependency ("field")]
+ [PreserveDependency ("Method2 (System.SByte&)")]
+ public static void SameContext ()
+ {
+ }
+
+ [Kept]
+ [PreserveDependency ("Missing", "Mono.Linker.Tests.Cases.Advanced.C")]
+ [PreserveDependency ("Dependency2`1 (T, System.Int32, System.Object)", "Mono.Linker.Tests.Cases.Advanced.C")]
+ [PreserveDependency ("")]
+ public static void Broken ()
+ {
+ }
+
+ [Kept]
+ [PreserveDependency ("ConditionalTest()", "Mono.Linker.Tests.Cases.Advanced.C", Condition = "don't have it")]
+ public static void Conditional ()
+ {
+ }
+ }
+
+ class Nested
+ {
+ [Kept]
+ private static void NextOne (ref Nested arg1)
+ {
+ }
+ }
+ }
+
+ class C
+ {
+ [Kept]
+ internal string field;
+
+ [Kept]
+ internal void Dependency1 ()
+ {
+ }
+
+ internal void Dependency1 (long arg1)
+ {
+ }
+
+ [Kept]
+ internal void Dependency2<T> (T[] arg1, int arg2)
+ {
+ }
+
+ [Kept]
+ [KeptBackingField]
+ internal string Property { [Kept] get; set; }
+
+ internal void ConditionalTest ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInAssembly.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInAssembly.cs
new file mode 100644
index 000000000..f3a258ebb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInAssembly.cs
@@ -0,0 +1,22 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies
+{
+ [KeptMemberInAssembly ("library.dll", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInAssemblyLibrary", ".ctor()")]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/PreserveDependencyMethodInAssemblyLibrary.cs" })]
+ public class PreserveDependencyMethodInAssembly
+ {
+ public static void Main ()
+ {
+ Dependency ();
+ }
+
+ [Kept]
+ [PreserveDependency (".ctor()", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInAssemblyLibrary", "library")]
+ static void Dependency ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssembly.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssembly.cs
new file mode 100644
index 000000000..b85e7cd58
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssembly.cs
@@ -0,0 +1,38 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs" })]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs" }, references: new [] { "base.dll" }, addAsReference: false)]
+ [KeptAssembly ("base.dll")]
+ [KeptAssembly ("library.dll")]
+ [KeptMemberInAssembly ("base.dll", typeof (PreserveDependencyMethodInNonReferencedAssemblyBase), "Method()")]
+ [KeptMemberInAssembly ("library.dll", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyLibrary", "Method()")]
+ public class PreserveDependencyMethodInNonReferencedAssembly {
+ public static void Main ()
+ {
+ var obj = new Foo ();
+ var val = obj.Method ();
+ Dependency ();
+ }
+
+ [Kept]
+ [PreserveDependency (".ctor()", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyLibrary", "library")]
+ static void Dependency ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (PreserveDependencyMethodInNonReferencedAssemblyBase))]
+ class Foo : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ [Kept]
+ public override string Method ()
+ {
+ return "Foo";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyChained.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyChained.cs
new file mode 100644
index 000000000..677fa113a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyChained.cs
@@ -0,0 +1,42 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ [IgnoreTestCase ("Currently failing")]
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs" })]
+ [SetupCompileBefore ("base2.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase2.cs" }, references: new [] { "base.dll" }, addAsReference: false)]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary.cs" }, references: new [] { "base.dll" }, addAsReference: false)]
+ [KeptAssembly ("base.dll")]
+ [KeptAssembly ("base2.dll")]
+ [KeptAssembly ("library.dll")]
+ [KeptMemberInAssembly ("base.dll", typeof (PreserveDependencyMethodInNonReferencedAssemblyBase), "Method()")]
+ [KeptMemberInAssembly ("base2.dll", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyBase2", "Method()")]
+ [KeptMemberInAssembly ("library.dll", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary", "Method()")]
+ public class PreserveDependencyMethodInNonReferencedAssemblyChained {
+ public static void Main ()
+ {
+ var obj = new Foo ();
+ var val = obj.Method ();
+ Dependency ();
+ }
+
+ [Kept]
+ [PreserveDependency (".ctor()", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary", "library")]
+ static void Dependency ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (PreserveDependencyMethodInNonReferencedAssemblyBase))]
+ class Foo : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ [Kept]
+ public override string Method ()
+ {
+ return "Foo";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReference.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReference.cs
new file mode 100644
index 000000000..e86d31476
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReference.cs
@@ -0,0 +1,45 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ [IgnoreTestCase ("Currently failing")]
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs" })]
+ [SetupCompileBefore ("base2.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase2.cs" }, references: new [] { "base.dll" }, addAsReference: false)]
+ [SetupCompileBefore ("reference.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary.cs" }, references: new [] { "base.dll" }, addAsReference: false)]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary.cs" }, references: new [] { "base.dll", "reference.dll" }, addAsReference: false)]
+ [KeptAssembly ("base.dll")]
+ [KeptAssembly ("base2.dll")]
+ [KeptAssembly ("library.dll")]
+ [KeptAssembly ("reference.dll")]
+ [KeptMemberInAssembly ("base.dll", typeof (PreserveDependencyMethodInNonReferencedAssemblyBase), "Method()")]
+ [KeptMemberInAssembly ("base2.dll", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyBase2", "Method()")]
+ [KeptMemberInAssembly ("library.dll", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary", "Method()")]
+ [KeptMemberInAssembly ("reference.dll", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyChainedLibrary", "Method()")]
+ public class PreserveDependencyMethodInNonReferencedAssemblyChainedReference {
+ public static void Main ()
+ {
+ var obj = new Foo ();
+ var val = obj.Method ();
+ Dependency ();
+ }
+
+ [Kept]
+ [PreserveDependency (".ctor()", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyChainedReferenceLibrary", "library")]
+ static void Dependency ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (PreserveDependencyMethodInNonReferencedAssemblyBase))]
+ class Foo : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ [Kept]
+ public override string Method ()
+ {
+ return "Foo";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyWithEmbeddedXml.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyWithEmbeddedXml.cs
new file mode 100644
index 000000000..12a989922
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyMethodInNonReferencedAssemblyWithEmbeddedXml.cs
@@ -0,0 +1,45 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ /// <summary>
+ /// This is an acceptable bug with the currently implementation. Embedded link xml files will not be processed
+ /// </summary>
+ [IncludeBlacklistStep (true)]
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs" })]
+ [SetupCompileBefore (
+ "PreserveDependencyMethodInNonReferencedAssemblyLibrary.dll",
+ new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs" },
+ references: new [] { "base.dll" },
+ resources: new [] {"Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.xml"},
+ addAsReference: false)]
+ [KeptAssembly ("base.dll")]
+ [RemovedMemberInAssembly ("PreserveDependencyMethodInNonReferencedAssemblyLibrary.dll", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyLibrary", "UnusedMethod()")]
+ public class PreserveDependencyMethodInNonReferencedAssemblyWithEmbeddedXml {
+ public static void Main ()
+ {
+ var obj = new Foo ();
+ var val = obj.Method ();
+ Dependency ();
+ }
+
+ [Kept]
+ [PreserveDependency (".ctor()", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyLibrary", "PreserveDependencyMethodInNonReferencedAssemblyLibrary")]
+ static void Dependency ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (PreserveDependencyMethodInNonReferencedAssemblyBase))]
+ class Foo : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ [Kept]
+ public override string Method ()
+ {
+ return "Foo";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssembly.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssembly.cs
new file mode 100644
index 000000000..6a407e55a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssembly.cs
@@ -0,0 +1,35 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs" })]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs" }, references: new [] { "base.dll" }, addAsReference: false)]
+ [KeptAssembly ("base.dll")]
+ [RemovedAssembly ("library.dll")]
+ [KeptMemberInAssembly ("base.dll", typeof (PreserveDependencyMethodInNonReferencedAssemblyBase), "Method()")]
+ public class PreserveDependencyOnUnusedMethodInNonReferencedAssembly {
+ public static void Main ()
+ {
+ var obj = new Foo ();
+ var val = obj.Method ();
+ }
+
+ [PreserveDependency (".ctor()", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyLibrary", "library")]
+ static void Dependency ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (PreserveDependencyMethodInNonReferencedAssemblyBase))]
+ class Foo : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ [Kept]
+ public override string Method ()
+ {
+ return "Foo";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction.cs
new file mode 100644
index 000000000..94ad0b56f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction.cs
@@ -0,0 +1,19 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ [SetupLinkerUserAction ("copyused")]
+ [SetupCompileBefore ("library.dll", new [] {"Dependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction_Lib.cs"}, addAsReference: false)]
+ [RemovedAssembly ("library.dll")]
+ public class PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction {
+ public static void Main ()
+ {
+ }
+
+ [PreserveDependency ("MethodPreservedViaDependencyAttribute()", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithCopyUsedAction_Lib", "library")]
+ static void Dependency ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithEmbeddedXml.cs b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithEmbeddedXml.cs
new file mode 100644
index 000000000..c9d61dfb0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/PreserveDependencies/PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithEmbeddedXml.cs
@@ -0,0 +1,43 @@
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.PreserveDependencies {
+ /// <summary>
+ /// This test is here to ensure that link xml embedded in an assembly used by a [PreserveDependency] is not processed if the dependency is not used
+ /// </summary>
+ [IncludeBlacklistStep (true)]
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyBase.cs" })]
+ [SetupCompileBefore (
+ "PreserveDependencyMethodInNonReferencedAssemblyLibrary.dll",
+ new [] { "Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.cs" },
+ references: new [] { "base.dll" },
+ resources: new [] {"Dependencies/PreserveDependencyMethodInNonReferencedAssemblyLibrary.xml"},
+ addAsReference: false)]
+ [KeptAssembly ("base.dll")]
+ [RemovedAssembly ("PreserveDependencyMethodInNonReferencedAssemblyLibrary.dll")]
+ public class PreserveDependencyOnUnusedMethodInNonReferencedAssemblyWithEmbeddedXml {
+ public static void Main ()
+ {
+ var obj = new Foo ();
+ var val = obj.Method ();
+ }
+
+ [PreserveDependency (".ctor()", "Mono.Linker.Tests.Cases.PreserveDependencies.Dependencies.PreserveDependencyMethodInNonReferencedAssemblyLibrary", "PreserveDependencyMethodInNonReferencedAssemblyLibrary")]
+ static void Dependency ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (PreserveDependencyMethodInNonReferencedAssemblyBase))]
+ class Foo : PreserveDependencyMethodInNonReferencedAssemblyBase {
+ [Kept]
+ public override string Method ()
+ {
+ return "Foo";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs
new file mode 100644
index 000000000..47309dbba
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCsc.cs
@@ -0,0 +1,30 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.References.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.References {
+ /// <summary>
+ /// We can't detect the using usage in the assembly. As a result, nothing in `library` is going to be marked and that assembly will be deleted.
+ /// Because of that, `copied` needs to have it's reference to `library` removed even though we specified an assembly action of `copy`
+ /// </summary>
+ [SetupLinkerAction ("copy", "copied")]
+ [SetupLinkerArgument ("--keep-facades", "false")]
+ [SetupCompileBefore ("library.dll", new [] {"Dependencies/AssemblyOnlyUsedByUsing_Lib.cs"})]
+
+ // When csc is used, `copied.dll` will have a reference to `library.dll`
+ [SetupCompileBefore ("copied.dll", new [] {"Dependencies/AssemblyOnlyUsedByUsing_Copied.cs"}, new [] {"library.dll"}, compilerToUse: "csc")]
+
+ // Here to assert that the test is setup correctly to copy the copied assembly. This is an important aspect of the bug
+ [KeptMemberInAssembly ("copied.dll", typeof (AssemblyOnlyUsedByUsing_Copied), "Unused()")]
+
+ // We library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked
+ [RemovedAssembly ("library.dll")]
+ [KeptReferencesInAssembly ("copied.dll", new [] {"mscorlib"})]
+ public class AssemblyOnlyUsedByUsingWithCsc {
+ public static void Main ()
+ {
+ // Use something to keep the reference at compile time
+ AssemblyOnlyUsedByUsing_Copied.UsedToKeepReference ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs
new file mode 100644
index 000000000..bf80d944f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithCscWithKeepFacades.cs
@@ -0,0 +1,32 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.References.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.References {
+ /// <summary>
+ /// We can't detect the using usage in the assembly. As a result, nothing in `library` is going to be marked and that assembly will be deleted.
+ /// Because of that, `copied` needs to have it's reference to `library` removed even though we specified an assembly action of `copy`
+ /// </summary>
+ [SetupLinkerAction ("copy", "copied")]
+
+ // --keep-facades sends the sweep step down a different code path that caused problems for this corner case
+ [SetupLinkerArgument ("--keep-facades", "true")]
+ [SetupCompileBefore ("library.dll", new [] {"Dependencies/AssemblyOnlyUsedByUsing_Lib.cs"})]
+
+ // When csc is used, `copied.dll` will have a reference to `library.dll`
+ [SetupCompileBefore ("copied.dll", new [] {"Dependencies/AssemblyOnlyUsedByUsing_Copied.cs"}, new [] {"library.dll"}, compilerToUse: "csc")]
+
+ // Here to assert that the test is setup correctly to copy the copied assembly. This is an important aspect of the bug
+ [KeptMemberInAssembly ("copied.dll", typeof (AssemblyOnlyUsedByUsing_Copied), "Unused()")]
+
+ // We library should be gone. The `using` statement leaves no traces in the IL so nothing in `library` will be marked
+ [RemovedAssembly ("library.dll")]
+ [KeptReferencesInAssembly ("copied.dll", new [] {"mscorlib"})]
+ public class AssemblyOnlyUsedByUsingWithCscWithKeepFacades {
+ public static void Main ()
+ {
+ // Use something to keep the reference at compile time
+ AssemblyOnlyUsedByUsing_Copied.UsedToKeepReference ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithMcs.cs b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithMcs.cs
new file mode 100644
index 000000000..aae6e2773
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/AssemblyOnlyUsedByUsingWithMcs.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.References.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.References {
+ [SetupLinkerAction ("copy", "copied")]
+ [SetupCompileBefore ("library.dll", new [] {"Dependencies/AssemblyOnlyUsedByUsing_Lib.cs"})]
+
+ // When mcs is used, `copied.dll` will not have a reference to `library.dll`
+ [SetupCompileBefore ("copied.dll", new [] {"Dependencies/AssemblyOnlyUsedByUsing_Copied.cs"}, new [] {"library.dll"}, compilerToUse: "mcs")]
+
+ // Here to assert that the test is setup correctly to copy the copied assembly. This is an important aspect of the bug
+ [KeptMemberInAssembly ("copied.dll", typeof (AssemblyOnlyUsedByUsing_Copied), "Unused()")]
+
+ [RemovedAssembly ("library.dll")]
+ [KeptReferencesInAssembly ("copied.dll", new [] {"mscorlib"})]
+ public class AssemblyOnlyUsedByUsingWithMcs {
+ public static void Main ()
+ {
+ // Use something to keep the reference at compile time
+ AssemblyOnlyUsedByUsing_Copied.UsedToKeepReference ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Copied.cs b/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Copied.cs
new file mode 100644
index 000000000..31552b32c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Copied.cs
@@ -0,0 +1,16 @@
+
+// This is what triggers the behavior difference between Roslyn and mcs. Roslyn will keep the reference
+// to this assembly because of this whereas mcs will not
+using ImportantForBug = Mono.Linker.Tests.Cases.References.Dependencies.AssemblyOnlyUsedByUsing_Lib;
+
+namespace Mono.Linker.Tests.Cases.References.Dependencies {
+ public class AssemblyOnlyUsedByUsing_Copied {
+ public static void UsedToKeepReference ()
+ {
+ }
+
+ private static void Unused ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Lib.cs b/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Lib.cs
new file mode 100644
index 000000000..7ec8becd0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/Dependencies/AssemblyOnlyUsedByUsing_Lib.cs
@@ -0,0 +1,4 @@
+namespace Mono.Linker.Tests.Cases.References.Dependencies {
+ public class AssemblyOnlyUsedByUsing_Lib {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/References/Dependencies/UserAssembliesAreLinkedByDefault_Library1.cs b/test/Mono.Linker.Tests.Cases/References/Dependencies/UserAssembliesAreLinkedByDefault_Library1.cs
new file mode 100644
index 000000000..d8a45ab93
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/Dependencies/UserAssembliesAreLinkedByDefault_Library1.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.References.Dependencies {
+ public class UserAssembliesAreLinkedByDefault_Library1 {
+ public void UsedMethod ()
+ {
+ Console.WriteLine ("Used");
+ }
+
+ public void UnusedMethod ()
+ {
+ Console.WriteLine ("NotUsed");
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/References/Individual/CanSkipUnresolved.cs b/test/Mono.Linker.Tests.Cases/References/Individual/CanSkipUnresolved.cs
new file mode 100644
index 000000000..ec502e894
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/Individual/CanSkipUnresolved.cs
@@ -0,0 +1,18 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.References.Individual.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.References.Individual {
+ [SetupCompileBefore ("library1.dll", new [] { "Dependencies/CanSkipUnresolved_Library.cs" })]
+ [SetupCompileAfter ("library1.dll", new [] { "Dependencies/CanSkipUnresolved_Library.cs" }, defines: new [] { "EXCLUDE_STUFF" })]
+ [SetupLinkerArgument ("--skip-unresolved", "true")]
+ public class CanSkipUnresolved {
+ static void Main ()
+ {
+ var t1 = new CanSkipUnresolved_Library.TypeWithMissingMethod ();
+ t1.GoingToBeMissing ();
+
+ var t2 = new CanSkipUnresolved_Library.TypeThatWillBeMissing ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/References/Individual/Dependencies/CanSkipUnresolved_Library.cs b/test/Mono.Linker.Tests.Cases/References/Individual/Dependencies/CanSkipUnresolved_Library.cs
new file mode 100644
index 000000000..59e5cff44
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/Individual/Dependencies/CanSkipUnresolved_Library.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.References.Individual.Dependencies {
+ public class CanSkipUnresolved_Library {
+ public class TypeWithMissingMethod {
+#if !EXCLUDE_STUFF
+ public void GoingToBeMissing ()
+ {
+
+ }
+#endif
+ }
+
+#if !EXCLUDE_STUFF
+ public class TypeThatWillBeMissing {
+ }
+#endif
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/References/ReferencesAreRemovedWhenAllUsagesAreRemoved.cs b/test/Mono.Linker.Tests.Cases/References/ReferencesAreRemovedWhenAllUsagesAreRemoved.cs
new file mode 100644
index 000000000..5132208e1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/ReferencesAreRemovedWhenAllUsagesAreRemoved.cs
@@ -0,0 +1,30 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.References {
+ [SetupLinkerCoreAction ("link")]
+ // Il8n & the blacklist step pollute the results with extra stuff that didn't need to be
+ // preserved for this test case so we need to disable them
+ [Il8n ("none")]
+ [Reference ("System.dll")]
+ [RemovedAssembly ("System.dll")]
+ [KeptReference ("mscorlib.dll")]
+ // Can be removed once this bug is fixed https://bugzilla.xamarin.com/show_bug.cgi?id=58168
+ [SkipPeVerify(SkipPeVerifyForToolchian.Pedump)]
+ // System.Core.dll is referenced by System.dll in the .NET FW class libraries. Our GetType reflection marking code
+ // detects a GetType("SHA256CryptoServiceProvider") in System.dll, which then causes a type in System.Core.dll to be marked.
+ // PeVerify fails on the original GAC copy of System.Core.dll so it's expected that it will also fail on the stripped version we output
+ [SkipPeVerify ("System.Core.dll")]
+ class ReferencesAreRemovedWhenAllUsagesAreRemoved {
+ public static void Main ()
+ {
+ }
+
+ private static void Unused ()
+ {
+ // Use something from System.dll so that we know the input assembly was compiled with the reference
+ var uri = new Uri ("w/e");
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/References/UserAssembliesAreLinkedByDefault.cs b/test/Mono.Linker.Tests.Cases/References/UserAssembliesAreLinkedByDefault.cs
new file mode 100644
index 000000000..0c68e127c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/References/UserAssembliesAreLinkedByDefault.cs
@@ -0,0 +1,18 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.References.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.References {
+ [SetupCompileBefore ("library1.dll", new [] { "Dependencies/UserAssembliesAreLinkedByDefault_Library1.cs" })]
+
+ [KeptAssembly ("library1.dll")]
+ [KeptMemberInAssembly ("library1.dll", typeof (UserAssembliesAreLinkedByDefault_Library1), "UsedMethod()")]
+ [RemovedMemberInAssembly ("library1.dll", typeof (UserAssembliesAreLinkedByDefault_Library1), "UnusedMethod()")]
+ class UserAssembliesAreLinkedByDefault {
+ public static void Main ()
+ {
+ new UserAssembliesAreLinkedByDefault_Library1 ().UsedMethod ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflection.cs
new file mode 100644
index 000000000..147c31c60
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflection.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Reflection
+{
+ [IgnoreTestCase ("Requires support for using a type in an unreferences assembly via reflection")]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/AssemblyDependency.cs" }, addAsReference: false)]
+ [KeptAssembly ("library.dll")]
+ [KeptTypeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyDependency")]
+ public class AssemblyImportedViaReflection
+ {
+ public static void Main ()
+ {
+ const string newAssemblyType = "Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyDependency, library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
+ var res = Type.GetType (newAssemblyType, true);
+ return;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflectionWithDerivedType.cs b/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflectionWithDerivedType.cs
new file mode 100644
index 000000000..5f4e8af1e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflectionWithDerivedType.cs
@@ -0,0 +1,40 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Reflection.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Reflection
+{
+ [IgnoreTestCase ("Requires support for using a type in an unreferences assembly via reflection")]
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/AssemblyImportedViaReflectionWithDerivedType_Base.cs" })]
+ [SetupCompileBefore ("reflection.dll", new [] { "Dependencies/AssemblyImportedViaReflectionWithDerivedType_Reflect.cs" }, references: new [] {"base.dll"}, addAsReference: false)]
+ [KeptAssembly ("base.dll")]
+ [KeptAssembly ("reflection.dll")]
+ [KeptMemberInAssembly ("base.dll", typeof (AssemblyImportedViaReflectionWithDerivedType_Base), "Method()")]
+ [KeptMemberInAssembly ("reflection.dll", "Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyImportedViaReflectionWithDerivedType_Reflect", "Method()")]
+ public class AssemblyImportedViaReflectionWithDerivedType
+ {
+ public static void Main ()
+ {
+ // Cause a the new assembly to be included via reflection usage
+ const string newAssemblyType = "Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyImportedViaReflectionWithDerivedType_Reflect, reflection, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
+ var res = Type.GetType (newAssemblyType, true);
+
+ // Foo and the reflection assembly both have a class the inherits from the base type.
+ // by using `Method` here and marking the reflection type above, we've introduced a requirement that `Method` be marked on the type in the reflection assembly as well
+ var obj = new Foo ();
+ var val = obj.Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ [KeptBaseType (typeof (AssemblyImportedViaReflectionWithDerivedType_Base))]
+ class Foo : AssemblyImportedViaReflectionWithDerivedType_Base {
+ [Kept]
+ public override string Method ()
+ {
+ return "Foo";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflectionWithReference.cs b/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflectionWithReference.cs
new file mode 100644
index 000000000..716207d22
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/AssemblyImportedViaReflectionWithReference.cs
@@ -0,0 +1,23 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Reflection
+{
+ [IgnoreTestCase ("Requires support for using a type in an unreferences assembly via reflection")]
+ [SetupCompileBefore ("reference.dll", new [] { "Dependencies/AssemblyDependency.cs" }, addAsReference: false)]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/AssemblyDependencyWithReference.cs" }, references: new []{"reference.dll"}, addAsReference: false)]
+ [KeptAssembly ("reference.dll")]
+ [KeptAssembly ("library.dll")]
+ [KeptTypeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyDependencyWithReference")]
+ [KeptTypeInAssembly ("reference.dll", "Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyDependency")]
+ public class AssemblyImportedViaReflectionWithReference
+ {
+ public static void Main ()
+ {
+ const string newAssemblyType = "Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyDependencyWithReference, library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
+ var res = Type.GetType (newAssemblyType, true);
+ return;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs
new file mode 100644
index 000000000..16851b0cf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/ConstructorUsedViaReflection.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection
+{
+ public class ConstructorUsedViaReflection {
+ public static void Main ()
+ {
+ var constructor = typeof (OnlyUsedViaReflection).GetConstructor (BindingFlags.Public, null, new Type[]{}, new ParameterModifier[]{});
+ constructor.Invoke (null, new object[] { });
+ }
+
+ [Kept]
+ private class OnlyUsedViaReflection {
+ [Kept]
+ public OnlyUsedViaReflection ()
+ { }
+
+ [Kept]
+ public OnlyUsedViaReflection(string bar)
+ { }
+
+ private OnlyUsedViaReflection (int foo)
+ { }
+
+ protected OnlyUsedViaReflection(int foo, int bar)
+ { }
+
+ internal OnlyUsedViaReflection(int foo, int bar, int baz)
+ { }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyDependency.cs b/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyDependency.cs
new file mode 100644
index 000000000..84339ad4b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyDependency.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Reflection.Dependencies
+{
+ public class AssemblyDependency
+ {
+ public AssemblyDependency ()
+ {
+ }
+
+ public static void UsedToKeepReferenceAtCompileTime ()
+ {
+ }
+
+ class TypeThatIsUsedViaReflection {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyDependencyWithReference.cs b/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyDependencyWithReference.cs
new file mode 100644
index 000000000..889b5e141
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyDependencyWithReference.cs
@@ -0,0 +1,4 @@
+namespace Mono.Linker.Tests.Cases.Reflection.Dependencies {
+ public class AssemblyDependencyWithReference : AssemblyDependency {
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyImportedViaReflectionWithDerivedType_Base.cs b/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyImportedViaReflectionWithDerivedType_Base.cs
new file mode 100644
index 000000000..6323951ee
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyImportedViaReflectionWithDerivedType_Base.cs
@@ -0,0 +1,5 @@
+namespace Mono.Linker.Tests.Cases.Reflection.Dependencies {
+ public abstract class AssemblyImportedViaReflectionWithDerivedType_Base {
+ public abstract string Method ();
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyImportedViaReflectionWithDerivedType_Reflect.cs b/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyImportedViaReflectionWithDerivedType_Reflect.cs
new file mode 100644
index 000000000..e0c1bcb2a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/Dependencies/AssemblyImportedViaReflectionWithDerivedType_Reflect.cs
@@ -0,0 +1,8 @@
+namespace Mono.Linker.Tests.Cases.Reflection.Dependencies {
+ public class AssemblyImportedViaReflectionWithDerivedType_Reflect : AssemblyImportedViaReflectionWithDerivedType_Base {
+ public override string Method ()
+ {
+ return "Reflect";
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs
new file mode 100644
index 000000000..774a46489
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/EventUsedViaReflection.cs
@@ -0,0 +1,18 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class EventUsedViaReflection {
+ public static void Main ()
+ {
+ var eventInfo = typeof (EventUsedViaReflection).GetEvent ("Event");
+ eventInfo.GetAddMethod (false);
+ }
+
+ [Kept]
+ [KeptBackingField]
+ [KeptEventAddMethod]
+ [KeptEventRemoveMethod]
+ event EventHandler<EventArgs> Event;
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs
new file mode 100644
index 000000000..c7c77abb5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/FieldUsedViaReflection.cs
@@ -0,0 +1,15 @@
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class FieldUsedViaReflection {
+ public static void Main ()
+ {
+ var field = typeof (FieldUsedViaReflection).GetField ("field");
+ field.GetValue (null);
+ }
+
+ [Kept]
+ static int field;
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs
new file mode 100644
index 000000000..39a7e12f4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflection.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class MethodUsedViaReflection {
+ public static void Main ()
+ {
+ var method = typeof (MethodUsedViaReflection).GetMethod ("OnlyCalledViaReflection", BindingFlags.Static | BindingFlags.NonPublic);
+ method.Invoke (null, new object[] { });
+ }
+
+ [Kept]
+ private static int OnlyCalledViaReflection ()
+ {
+ return 42;
+ }
+
+ private int OnlyCalledViaReflection (int foo)
+ {
+ return 43;
+ }
+
+ public int OnlyCalledViaReflection (int foo, int bar)
+ {
+ return 44;
+ }
+
+ public static int OnlyCalledViaReflection (int foo, int bar, int baz)
+ {
+ return 45;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflectionWithDefaultBindingFlags.cs b/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflectionWithDefaultBindingFlags.cs
new file mode 100644
index 000000000..7a2a4ae10
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/MethodUsedViaReflectionWithDefaultBindingFlags.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class MethodUsedViaReflectionWithDefaultBindingFlags {
+ public static void Main ()
+ {
+ var method = typeof (MethodUsedViaReflectionWithDefaultBindingFlags).GetMethod ("OnlyCalledViaReflection");
+ method.Invoke (null, new object[] { });
+ }
+
+ [Kept]
+ private static int OnlyCalledViaReflection ()
+ {
+ return 42;
+ }
+
+ [Kept]
+ private int OnlyCalledViaReflection (int foo)
+ {
+ return 43;
+ }
+
+ [Kept]
+ public int OnlyCalledViaReflection (int foo, int bar)
+ {
+ return 44;
+ }
+
+ [Kept]
+ public static int OnlyCalledViaReflection (int foo, int bar, int baz)
+ {
+ return 45;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/MightKeepExtraThings.cs b/test/Mono.Linker.Tests.Cases/Reflection/MightKeepExtraThings.cs
new file mode 100644
index 000000000..b5b6a1c52
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/MightKeepExtraThings.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class MightKeepExtraThings {
+ public static void Main ()
+ {
+ var typeA = typeof (A);
+ var typeB = typeof (B);
+ Console.WriteLine (typeB); // Use typeB so the C# compiler keeps it in the IL code.
+ var method = typeA.GetMethod ("Foo", BindingFlags.Public);
+ method.Invoke (null, new object[] { });
+ }
+
+ [Kept]
+ public class A {
+ [Kept]
+ public int Foo ()
+ {
+ return 42;
+ }
+ }
+
+ [Kept]
+ public class B {
+ [Kept]
+ public int Foo ()
+ {
+ return 43;
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs
new file mode 100644
index 000000000..2dc55aa2c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/PropertyUsedViaReflection.cs
@@ -0,0 +1,40 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class PropertyUsedViaReflection {
+ public static void Main ()
+ {
+ var property = typeof (PropertyUsedViaReflection).GetProperty ("OnlyUsedViaReflection");
+ property.GetValue (null, new object[] { });
+
+ property = typeof (PropertyUsedViaReflection).GetProperty ("SetterOnly");
+ property.SetValue (null, 42, new object[] { });
+
+ property = typeof (PropertyUsedViaReflection).GetProperty ("GetterOnly");
+ property.GetValue (null, new object[] { });
+ }
+
+ [Kept]
+ static int _field;
+
+ [Kept]
+ static int OnlyUsedViaReflection {
+ [Kept]
+ get { return _field; }
+ [Kept]
+ set { _field = value; }
+ }
+
+ [Kept]
+ static int SetterOnly {
+ [Kept]
+ set { _field = value; }
+ }
+
+ [Kept]
+ static int GetterOnly {
+ [Kept]
+ get { return _field; }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs
new file mode 100644
index 000000000..1fcef6673
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflection.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class TypeUsedViaReflection {
+ public static void Main ()
+ {
+ TestNull ();
+ TestEmptyString ();
+ TestFullString ();
+ TestGenericString ();
+ TestFullStringConst();
+ TestTypeAsmName ();
+ TestType ();
+ TestPointer ();
+ TestReference ();
+ TestArray ();
+ TestArrayOfArray ();
+ TestMultiDimensionalArray ();
+ TestMultiDimensionalArrayFullString ();
+ TestMultiDimensionalArrayAsmName ();
+ }
+
+ [Kept]
+ public static void TestNull ()
+ {
+ string reflectionTypeKeptString = null;
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public static void TestEmptyString ()
+ {
+ string reflectionTypeKeptString = "";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class Full { }
+
+ [Kept]
+ public static void TestFullString ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+Full, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class Generic<T> { }
+
+ [Kept]
+ public static void TestGenericString ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+Generic`1, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class FullConst { }
+
+ [Kept]
+ public static void TestFullStringConst()
+ {
+ const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+FullConst, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
+ var typeKept = Type.GetType(reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class TypeAsmName { }
+
+ [Kept]
+ public static void TestTypeAsmName ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+TypeAsmName, test";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class AType { }
+
+ [Kept]
+ public static void TestType ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AType";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class Pointer { }
+
+ [Kept]
+ public static void TestPointer ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+Pointer*";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class Reference { }
+
+ [Kept]
+ public static void TestReference ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+Reference&";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class Array { }
+
+ [Kept]
+ public static void TestArray ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+Array[]";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class ArrayOfArray{ }
+
+ [Kept]
+ public static void TestArrayOfArray ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+ArrayOfArray[][]";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+
+ [Kept]
+ public class MultiDimensionalArray{ }
+
+ [Kept]
+ public static void TestMultiDimensionalArray ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+MultiDimensionalArray[,]";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class MultiDimensionalArrayFullString { }
+
+ [Kept]
+ public static void TestMultiDimensionalArrayFullString ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+MultiDimensionalArrayFullString[,], test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+
+ [Kept]
+ public class MultiDimensionalArrayAsmName { }
+
+ [Kept]
+ public static void TestMultiDimensionalArrayAsmName ()
+ {
+ var reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+MultiDimensionalArrayAsmName[,], test";
+ var typeKept = Type.GetType (reflectionTypeKeptString, false);
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionAssemblyDoesntExist.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionAssemblyDoesntExist.cs
new file mode 100644
index 000000000..1311ac46f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionAssemblyDoesntExist.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class TypeUsedViaReflectionAssemblyDoesntExist {
+ public static void Main ()
+ {
+ var typeName = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflectionAssemblyDoesntExist+DoesntExist, test";
+ var typeKept = Type.GetType (typeName, false);
+ }
+
+ public class Full { }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionInDifferentAssembly.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionInDifferentAssembly.cs
new file mode 100644
index 000000000..8df8ee25d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionInDifferentAssembly.cs
@@ -0,0 +1,23 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Reflection.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/AssemblyDependency.cs" })]
+ [KeptAssembly ("library.dll")]
+ [KeptTypeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyDependency/TypeThatIsUsedViaReflection")]
+ public class TypeUsedViaReflectionInDifferentAssembly {
+ public static void Main ()
+ {
+ AssemblyDependency.UsedToKeepReferenceAtCompileTime ();
+ Helper ();
+ }
+
+ [Kept]
+ static Type Helper ()
+ {
+ return Type.GetType ("Mono.Linker.Tests.Cases.Reflection.Dependencies.AssemblyDependency+TypeThatIsUsedViaReflection, library");
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionLdstrIncomplete.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionLdstrIncomplete.cs
new file mode 100644
index 000000000..56c1077bf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionLdstrIncomplete.cs
@@ -0,0 +1,24 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ /// <summary>
+ /// This case we can't detect and need to gracefully do nothing
+ /// </summary>
+ public class TypeUsedViaReflectionLdstrIncomplete {
+ public static void Main ()
+ {
+ var typePart = GetTypePart ();
+ var assemblyPart = ",test";
+ var typeKept = Type.GetType (string.Concat (typePart, assemblyPart), false);
+ }
+
+ public class Full { }
+
+ [Kept]
+ static string GetTypePart ()
+ {
+ return "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflectionLdstrIncomplete+Full";
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionLdstrValidButChanged.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionLdstrValidButChanged.cs
new file mode 100644
index 000000000..c4e6b6a38
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionLdstrValidButChanged.cs
@@ -0,0 +1,21 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ /// <summary>
+ /// We don't know if `typeName` will be changed or not. If we error on the side of caution and preserve something
+ /// that we found, I don't think that's a big deal
+ /// </summary>
+ public class TypeUsedViaReflectionLdstrValidButChanged {
+ public static void Main ()
+ {
+ var replace = "Mono.Linker";
+ var with = "Blah.Blah";
+ var typeName = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflectionLdstrValidButChanged+Full, test";
+ var typeKept = Type.GetType (typeName.Replace (replace, with), false);
+ }
+
+ [Kept]
+ public class Full { }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionTypeDoesntExist.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionTypeDoesntExist.cs
new file mode 100644
index 000000000..067d08739
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionTypeDoesntExist.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class TypeUsedViaReflectionTypeDoesntExist {
+ public static void Main ()
+ {
+ var typeName = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflectionTypeDoesntExist+Full, DoesntExist";
+ var typeKept = Type.GetType (typeName, false);
+ }
+
+ public class Full { }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionTypeNameIsSymbol.cs b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionTypeNameIsSymbol.cs
new file mode 100644
index 000000000..70500994e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/TypeUsedViaReflectionTypeNameIsSymbol.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Reflection {
+ public class TypeUsedViaReflectionTypeNameIsSymbol {
+ public static void Main ()
+ {
+ var typeName = "+, test";
+ var typeKept = Type.GetType (typeName, false);
+ }
+
+ public class Full { }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Reflection/UsedViaReflectionIntegrationTest.cs b/test/Mono.Linker.Tests.Cases/Reflection/UsedViaReflectionIntegrationTest.cs
new file mode 100644
index 000000000..e0f7edd79
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Reflection/UsedViaReflectionIntegrationTest.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Reflection
+{
+ public class UsedViaReflectionIntegrationTest
+ {
+ public static void Main ()
+ {
+ var test = 42;
+
+ var constructor = typeof (OnlyUsedViaReflection).GetConstructor (BindingFlags.Public, null, new Type [] { }, new ParameterModifier [] { });
+ constructor.Invoke(null, new object[] { });
+
+ if (test == 42) {
+ var method = typeof (OnlyUsedViaReflection).GetMethod ("OnlyCalledViaReflection", BindingFlags.Static | BindingFlags.NonPublic);
+ method.Invoke (null, new object [] { });
+ }
+ }
+
+ [Kept]
+ private class OnlyUsedViaReflection
+ {
+ [Kept]
+ public OnlyUsedViaReflection ()
+ { }
+
+ [Kept]
+ public OnlyUsedViaReflection (string bar)
+ { }
+
+ private OnlyUsedViaReflection (int foo)
+ { }
+
+ protected OnlyUsedViaReflection (int foo, int bar)
+ { }
+
+ internal OnlyUsedViaReflection (int foo, int bar, int baz)
+ { }
+
+ [Kept]
+ private static int OnlyCalledViaReflection ()
+ {
+ return 42;
+ }
+
+ private int OnlyCalledViaReflection (int foo)
+ {
+ return 43;
+ }
+
+ public int OnlyCalledViaReflection (int foo, int bar)
+ {
+ return 44;
+ }
+
+ public static int OnlyCalledViaReflection (int foo, int bar, int baz)
+ {
+ return 45;
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.cs b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.cs
new file mode 100644
index 000000000..e90010c7b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.cs
@@ -0,0 +1,11 @@
+namespace Mono.Linker.Tests.Cases.Resources.Dependencies {
+ public class EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1 {
+ public static void Used ()
+ {
+ }
+
+ public static void Unused ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.xml b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.xml
new file mode 100644
index 000000000..6547ff296
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Resources.Dependencies.EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1" preserve="all">
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1.cs b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1.cs
new file mode 100644
index 000000000..a1ca4d678
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1.cs
@@ -0,0 +1,11 @@
+namespace Mono.Linker.Tests.Cases.Resources.Dependencies {
+ public class EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1 {
+ public static void Used ()
+ {
+ }
+
+ public static void Unused ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1_NotMatchingName.xml b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1_NotMatchingName.xml
new file mode 100644
index 000000000..3ee976f4c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1_NotMatchingName.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="library, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Resources.Dependencies.EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1" preserve="all">
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.cs b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.cs
new file mode 100644
index 000000000..65e1ef600
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.cs
@@ -0,0 +1,11 @@
+namespace Mono.Linker.Tests.Cases.Resources.Dependencies {
+ public class EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1 {
+ public static void Used ()
+ {
+ }
+
+ public static void Unused ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.xml b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.xml
new file mode 100644
index 000000000..9f01cc0e1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.xml
@@ -0,0 +1,6 @@
+<linker>
+ <assembly fullname="EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Resources.Dependencies.EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1" preserve="all">
+ </type>
+ </assembly>
+</linker>
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.xml b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.xml
new file mode 100644
index 000000000..8494ad013
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Resources.EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly/Unused" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.xml b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.xml
new file mode 100644
index 000000000..11c0c1f42
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Resources.EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled/Unused" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsProcessed.xml b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsProcessed.xml
new file mode 100644
index 000000000..518addf3d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsProcessed.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Resources.EmbeddedLinkXmlFileIsProcessed/Unused" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsProcessedAndKept.xml b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsProcessedAndKept.xml
new file mode 100644
index 000000000..84d733343
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/EmbeddedLinkXmlFileIsProcessedAndKept.xml
@@ -0,0 +1,5 @@
+<linker>
+ <assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ <type fullname="Mono.Linker.Tests.Cases.Resources.EmbeddedLinkXmlFileIsProcessedAndKept/Unused" />
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/Dependencies/NonLinkerEmbeddedResourceHasNoImpact.xml b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/NonLinkerEmbeddedResourceHasNoImpact.xml
new file mode 100644
index 000000000..1fb65aa9f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/Dependencies/NonLinkerEmbeddedResourceHasNoImpact.xml
@@ -0,0 +1,2 @@
+<someotherxmlformat>
+</someotherxmlformat> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy.cs b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy.cs
new file mode 100644
index 000000000..05cb22124
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Resources.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Resources {
+ [SetupCompileBefore (
+ "EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.dll",
+ new [] { "Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.cs" },
+ resources: new [] {"Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.xml"})]
+ [SetupLinkerAction ("copy", "EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1")]
+ [IncludeBlacklistStep (true)]
+
+ [KeptResourceInAssembly ("EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.dll", "EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.xml")]
+ [KeptMemberInAssembly ("EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.dll", typeof (EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1), "Unused()")]
+ public class EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy {
+ public static void Main ()
+ {
+ EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfActionIsCopy_Lib1.Used ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly.cs b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly.cs
new file mode 100644
index 000000000..4259b1c58
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly.cs
@@ -0,0 +1,20 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Resources.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Resources {
+ [SetupCompileBefore (
+ "library.dll",
+ new [] { "Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1.cs" },
+ resources: new [] {"Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1_NotMatchingName.xml"})]
+ [IncludeBlacklistStep (true)]
+
+ [KeptResourceInAssembly ("library.dll", "EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1_NotMatchingName.xml")]
+ [RemovedMemberInAssembly ("library.dll", typeof (EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1), "Unused()")]
+ public class EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly {
+ public static void Main ()
+ {
+ EmbeddedLinkXmlFileInReferencedAssemblyIsNotProcessedIfNameDoesNotMatchAnAssembly_Lib1.Used ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink.cs b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink.cs
new file mode 100644
index 000000000..8b477c037
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Resources.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Resources {
+ [SetupCompileBefore (
+ "EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.dll",
+ new [] { "Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.cs" },
+ resources: new [] {"Dependencies/EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.xml"})]
+ [SetupLinkerAction ("link", "EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1")]
+ [IncludeBlacklistStep (true)]
+
+ [RemovedResourceInAssembly ("EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.dll", "EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.xml")]
+ [KeptMemberInAssembly ("EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.dll", typeof (EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1), "Unused()")]
+ public class EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink {
+ public static void Main ()
+ {
+ EmbeddedLinkXmlFileInReferencedAssemblyIsProcessedIfActionIsLink_Lib1.Used ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs
new file mode 100644
index 000000000..69d1d1dc4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.cs
@@ -0,0 +1,19 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Resources {
+ [SetupLinkerCoreAction ("link")]
+ [IncludeBlacklistStep (true)]
+ [SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly.xml", "NotMatchingAnAssemblyName.xml")]
+ [SkipPeVerify]
+ [KeptResource ("NotMatchingAnAssemblyName.xml")]
+ public class EmbeddedLinkXmlFileIsNotProcessedIfNameDoesNotMatchAnAssembly {
+ public static void Main ()
+ {
+ }
+
+ public class Unused {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.cs b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.cs
new file mode 100644
index 000000000..604520899
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.cs
@@ -0,0 +1,21 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Resources {
+ [SetupLinkerCoreAction ("link")]
+ [IncludeBlacklistStep (false)]
+
+ // We need to rename the resource so that it matches the name of an assembly being processed. This is a requriement of the black list step
+ [SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled.xml", "test.xml")]
+ [SkipPeVerify]
+ [KeptResource ("test.xml")]
+ public class EmbeddedLinkXmlFileIsNotProcessedWhenBlacklistStepIsDisabled {
+ public static void Main ()
+ {
+ }
+
+ public class Unused {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessed.cs b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessed.cs
new file mode 100644
index 000000000..c7a043aaf
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessed.cs
@@ -0,0 +1,22 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Resources {
+ [SetupLinkerCoreAction ("link")]
+ [IncludeBlacklistStep (true)]
+
+ // We need to rename the resource so that it matches the name of an assembly being processed. This is a requriement of the black list step
+ [SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsProcessed.xml", "test.xml")]
+ [SkipPeVerify]
+ public class EmbeddedLinkXmlFileIsProcessed {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class Unused {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedAndKept.cs b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedAndKept.cs
new file mode 100644
index 000000000..a6b25d31b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/EmbeddedLinkXmlFileIsProcessedAndKept.cs
@@ -0,0 +1,25 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Resources
+{
+ [SetupLinkerCoreAction ("link")]
+ [IncludeBlacklistStep (true)]
+ [StripResources (false)]
+
+ // We need to rename the resource so that it matches the name of an assembly being processed. This is a requriement of the black list step
+ [SetupCompileResource ("Dependencies/EmbeddedLinkXmlFileIsProcessedAndKept.xml", "test.xml")]
+ [SkipPeVerify]
+ [KeptResource ("test.xml")]
+ public class EmbeddedLinkXmlFileIsProcessedAndKept {
+ public static void Main ()
+ {
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ public class Unused {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Resources/NonLinkerEmbeddedResourceHasNoImpact.cs b/test/Mono.Linker.Tests.Cases/Resources/NonLinkerEmbeddedResourceHasNoImpact.cs
new file mode 100644
index 000000000..b2112b92f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Resources/NonLinkerEmbeddedResourceHasNoImpact.cs
@@ -0,0 +1,18 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Resources {
+ [SetupLinkerCoreAction ("link")]
+ [IncludeBlacklistStep (true)]
+
+ // We need to rename the resource so that it matches the name of an assembly being processed. This is a requriement of the black list step
+ [SetupCompileResource ("Dependencies/NonLinkerEmbeddedResourceHasNoImpact.xml", "test.xml")]
+ [SkipPeVerify]
+ [KeptResource ("test.xml")]
+ public class NonLinkerEmbeddedResourceHasNoImpact {
+ public static void Main ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Statics/DisableBeforeFieldInit/UnusedStaticFieldInitializer.cs b/test/Mono.Linker.Tests.Cases/Statics/DisableBeforeFieldInit/UnusedStaticFieldInitializer.cs
new file mode 100644
index 000000000..a74d1a567
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Statics/DisableBeforeFieldInit/UnusedStaticFieldInitializer.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Statics.DisableBeforeFieldInit
+{
+ [SetupLinkerArgument ("--disable-opt", "BeforeFieldInit")]
+ public class UnusedStaticFieldInitializer
+ {
+ public static void Main ()
+ {
+ C.Foo ();
+ }
+
+ [KeptMember (".cctor()")]
+ static class C
+ {
+ [Kept]
+ public static object o = new object ();
+
+ [Kept]
+ public static void Foo ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Statics/ExplicitStaticCtor.cs b/test/Mono.Linker.Tests.Cases/Statics/ExplicitStaticCtor.cs
new file mode 100644
index 000000000..5c1d85343
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Statics/ExplicitStaticCtor.cs
@@ -0,0 +1,48 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Statics
+{
+ [SetupCompileArgument ("/optimize+")]
+ public class ExplicitStaticCtor
+ {
+ public static void Main ()
+ {
+ C.Foo ();
+ CEmpty.Foo ();
+ }
+
+ static class C
+ {
+ [Kept]
+ static C ()
+ {
+ new object ();
+ }
+
+ [Kept]
+ public static void Foo ()
+ {
+ }
+ }
+
+ [AddedPseudoAttributeAttribute ((uint)TypeAttributes.BeforeFieldInit)]
+ static class CEmpty
+ {
+ static CEmpty ()
+ {
+ }
+
+ [Kept]
+ public static void Foo ()
+ {
+ ++count;
+ }
+
+ [Kept]
+ static int count;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Statics/MixedStaticFieldInitializerAndCtor.cs b/test/Mono.Linker.Tests.Cases/Statics/MixedStaticFieldInitializerAndCtor.cs
new file mode 100644
index 000000000..da0a68714
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Statics/MixedStaticFieldInitializerAndCtor.cs
@@ -0,0 +1,28 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Statics
+{
+ public class MixedStaticFieldInitializerAndCtor
+ {
+ public static void Main ()
+ {
+ C.Foo ();
+ }
+
+ static class C
+ {
+ [Kept]
+ public static object o = new object ();
+
+ [Kept]
+ static C ()
+ {
+ }
+
+ [Kept]
+ public static void Foo ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Statics/StaticFieldInitializer.cs b/test/Mono.Linker.Tests.Cases/Statics/StaticFieldInitializer.cs
new file mode 100644
index 000000000..8e460e091
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Statics/StaticFieldInitializer.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Statics
+{
+ public class StaticFieldInitializer
+ {
+ public static void Main ()
+ {
+ C.Foo ();
+ }
+
+ [KeptMember(".cctor()")]
+ static class C
+ {
+ [Kept]
+ public static object o = new object ();
+
+ [Kept]
+ public static object Foo ()
+ {
+ return o;
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticConstructorGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticConstructorGetsRemoved.cs
new file mode 100644
index 000000000..83c1d1ea8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticConstructorGetsRemoved.cs
@@ -0,0 +1,20 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Statics {
+ class UnusedStaticConstructorGetsRemoved {
+ public static void Main ()
+ {
+ }
+
+ static void Dead ()
+ {
+ new B ();
+ }
+
+ class B {
+ static B ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticFieldInitializer.cs b/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticFieldInitializer.cs
new file mode 100644
index 000000000..5f0b96f77
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticFieldInitializer.cs
@@ -0,0 +1,22 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Statics
+{
+ public class UnusedStaticFieldInitializer
+ {
+ public static void Main ()
+ {
+ C.Foo ();
+ }
+
+ static class C
+ {
+ public static object o = new object ();
+
+ [Kept]
+ public static void Foo ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticMethodGetsRemoved.cs b/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticMethodGetsRemoved.cs
new file mode 100644
index 000000000..31c7c6ef0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Statics/UnusedStaticMethodGetsRemoved.cs
@@ -0,0 +1,23 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.Statics {
+ public class UnusedStaticMethodGetsRemoved {
+ public static void Main ()
+ {
+ A.UsedMethod ();
+ }
+ }
+
+ [Kept]
+ class A {
+ [Kept]
+ public static void UsedMethod ()
+ {
+ }
+
+ static void UnusedMethod ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/AssemblyWithDefaultSymbols.cs b/test/Mono.Linker.Tests.Cases/Symbols/AssemblyWithDefaultSymbols.cs
new file mode 100644
index 000000000..eb8b2bb16
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/AssemblyWithDefaultSymbols.cs
@@ -0,0 +1,15 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileArgument ("/debug:full")]
+ [SetupLinkerLinkSymbols ("false")]
+ [RemovedSymbols ("test.exe")]
+ public class AssemblyWithDefaultSymbols {
+ static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/AssemblyWithDefaultSymbolsAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/AssemblyWithDefaultSymbolsAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..b861f0eb8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/AssemblyWithDefaultSymbolsAndSymbolLinkingEnabled.cs
@@ -0,0 +1,15 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileArgument ("/debug:full")]
+ [SetupLinkerLinkSymbols ("true")]
+ [KeptSymbols ("test.exe")]
+ public class AssemblyWithDefaultSymbolsAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithCompilerDefaultSymbols.cs b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithCompilerDefaultSymbols.cs
new file mode 100644
index 000000000..38de58e93
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithCompilerDefaultSymbols.cs
@@ -0,0 +1,11 @@
+namespace Mono.Linker.Tests.Cases.Symbols.Dependencies {
+ public class LibraryWithCompilerDefaultSymbols {
+ public static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithEmbeddedPdbSymbols.cs b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithEmbeddedPdbSymbols.cs
new file mode 100644
index 000000000..578d8bf36
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithEmbeddedPdbSymbols.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Symbols.Dependencies {
+ public class LibraryWithEmbeddedPdbSymbols {
+ public static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.cs b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.cs
new file mode 100644
index 000000000..efb2d5481
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.cs
@@ -0,0 +1,11 @@
+namespace Mono.Linker.Tests.Cases.Symbols.Dependencies {
+ public class LibraryWithMdb {
+ public static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.dll b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.dll
new file mode 100755
index 000000000..574071f27
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.dll
Binary files differ
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb
new file mode 100644
index 000000000..0a1dee3e7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb
Binary files differ
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/compile.sh b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/compile.sh
new file mode 100755
index 000000000..023ed3cf7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithMdb/compile.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Run this script from a VS command prompt
+
+BASEDIR=$(dirname $0)
+mcs /debug:full /out:$BASEDIR/LibraryWithMdb.dll /target:library $BASEDIR/LibraryWithMdb.cs
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.cs b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.cs
new file mode 100644
index 000000000..339c836fe
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.cs
@@ -0,0 +1,11 @@
+namespace Mono.Linker.Tests.Cases.Symbols.Dependencies {
+ public class LibraryWithPdb {
+ public static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.dll b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.dll
new file mode 100644
index 000000000..66b764d0c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.dll
Binary files differ
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.pdb b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.pdb
new file mode 100644
index 000000000..f18c63de2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/LibraryWithPdb.pdb
Binary files differ
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/compile.bat b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/compile.bat
new file mode 100644
index 000000000..8ffff2143
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPdb/compile.bat
@@ -0,0 +1,5 @@
+@ECHO OFF
+
+REM Run this script from a VS command prompt
+
+csc /debug:full /out:%~dp0LibraryWithPdb.dll /target:library %~dp0LibraryWithPdb.cs
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPortablePdbSymbols.cs b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPortablePdbSymbols.cs
new file mode 100644
index 000000000..0c574f554
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/Dependencies/LibraryWithPortablePdbSymbols.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.Symbols.Dependencies {
+ public class LibraryWithPortablePdbSymbols {
+ public static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdb.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdb.cs
new file mode 100644
index 000000000..d79b85df3
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdb.cs
@@ -0,0 +1,20 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedSymbols ("LibraryWithEmbeddedPdbSymbols.dll")]
+
+ [KeptMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof (LibraryWithEmbeddedPdbSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof (LibraryWithEmbeddedPdbSymbols), "NotUsed()")]
+ class ReferenceWithEmbeddedPdb {
+ static void Main ()
+ {
+ LibraryWithEmbeddedPdbSymbols.SomeMethod ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..e99e5701b
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled.cs
@@ -0,0 +1,20 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("true")]
+
+ [KeptSymbols ("LibraryWithEmbeddedPdbSymbols.dll")]
+
+ [KeptMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof (LibraryWithEmbeddedPdbSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof (LibraryWithEmbeddedPdbSymbols), "NotUsed()")]
+ class ReferenceWithEmbeddedPdbAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ LibraryWithEmbeddedPdbSymbols.SomeMethod ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs
new file mode 100644
index 000000000..d58ef3041
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyAction.cs
@@ -0,0 +1,21 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("false")]
+ [SetupLinkerAction ("copy", "LibraryWithEmbeddedPdbSymbols")]
+
+ [RemovedSymbols ("LibraryWithEmbeddedPdbSymbols.dll")]
+
+ // Copying with symbol linking off is a little more complex for embedded pdbs.
+ // Do a little extra asserting here to make sure the assembly wasn't accidentally linked
+ [KeptMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof (LibraryWithEmbeddedPdbSymbols), "NotUsed()")]
+ public class ReferenceWithEmbeddedPdbCopyAction {
+ static void Main ()
+ {
+ LibraryWithEmbeddedPdbSymbols.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..ca173f827
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled.cs
@@ -0,0 +1,17 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("true")]
+ [SetupLinkerAction ("copy", "LibraryWithEmbeddedPdbSymbols")]
+
+ [KeptSymbols ("LibraryWithEmbeddedPdbSymbols.dll")]
+ public class ReferenceWithEmbeddedPdbCopyActionAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ LibraryWithEmbeddedPdbSymbols.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteAction.cs
new file mode 100644
index 000000000..ecbe6aa89
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteAction.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedAssembly ("LibraryWithEmbeddedPdbSymbols.dll")]
+ [RemovedSymbols ("LibraryWithEmbeddedPdbSymbols.dll")]
+ public class ReferenceWithEmbeddedPdbDeleteAction {
+ static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// By not using this method we will cause the linker to delete the reference
+ /// </summary>
+ static void UnusedCodePath ()
+ {
+ LibraryWithEmbeddedPdbSymbols.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..d31e0753f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("true")]
+
+ [RemovedAssembly ("LibraryWithEmbeddedPdbSymbols.dll")]
+ [RemovedSymbols ("LibraryWithEmbeddedPdbSymbols.dll")]
+ public class ReferenceWithEmbeddedPdbDeleteActionAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// By not using this method we will cause the linker to delete the reference
+ /// </summary>
+ static void UnusedCodePath ()
+ {
+ LibraryWithEmbeddedPdbSymbols.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdb.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdb.cs
new file mode 100644
index 000000000..657317dda
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdb.cs
@@ -0,0 +1,33 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedSymbols ("LibraryWithMdb.dll")]
+
+ [KeptMemberInAssembly ("LibraryWithMdb.dll", typeof (LibraryWithMdb), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithMdb.dll", typeof (LibraryWithMdb), "NotUsed()")]
+ public class ReferenceWithMdb {
+ static void Main()
+ {
+ // Use some stuff so that we can verify that the linker output correct results
+ SomeMethod ();
+
+ LibraryWithMdb.SomeMethod ();
+ }
+
+ [Kept]
+ static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..5b6961974
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbAndSymbolLinkingEnabled.cs
@@ -0,0 +1,33 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb")]
+ [SetupLinkerLinkSymbols ("true")]
+
+ [KeptSymbols ("LibraryWithMdb.dll")]
+
+ [KeptMemberInAssembly ("LibraryWithMdb.dll", typeof (LibraryWithMdb), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithMdb.dll", typeof (LibraryWithMdb), "NotUsed()")]
+ public class ReferenceWithMdbAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ // Use some stuff so that we can verify that the linker output correct results
+ SomeMethod ();
+
+ LibraryWithMdb.SomeMethod ();
+ }
+
+ [Kept]
+ static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbCopyAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbCopyAction.cs
new file mode 100644
index 000000000..9be79875e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbCopyAction.cs
@@ -0,0 +1,18 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb")]
+ [SetupLinkerLinkSymbols ("false")]
+ [SetupLinkerAction ("copy", "LibraryWithMdb")]
+
+ [RemovedSymbols ("LibraryWithMdb.dll")]
+ public class ReferenceWithMdbCopyAction {
+ static void Main ()
+ {
+ LibraryWithMdb.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbCopyActionAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbCopyActionAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..6dcf76fa7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbCopyActionAndSymbolLinkingEnabled.cs
@@ -0,0 +1,18 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb")]
+ [SetupLinkerLinkSymbols ("true")]
+ [SetupLinkerAction ("copy", "LibraryWithMdb")]
+
+ [KeptSymbols ("LibraryWithMdb.dll")]
+ public class ReferenceWithMdbCopyActionAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ LibraryWithMdb.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbDeleteAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbDeleteAction.cs
new file mode 100644
index 000000000..7b8ce67d7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbDeleteAction.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedAssembly ("LibraryWithMdb.dll")]
+ [RemovedSymbols ("LibraryWithMdb.dll")]
+ public class ReferenceWithMdbDeleteAction {
+ static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// By not using this method we will cause the linker to delete the reference
+ /// </summary>
+ static void UnusedCodePath ()
+ {
+ LibraryWithMdb.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbDeleteActionAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbDeleteActionAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..1f32f61ef
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithMdbDeleteActionAndSymbolLinkingEnabled.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb")]
+ [SetupLinkerLinkSymbols ("true")]
+
+ [RemovedAssembly ("LibraryWithMdb.dll")]
+ [RemovedSymbols ("LibraryWithMdb.dll")]
+ public class ReferenceWithMdbDeleteActionAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// By not using this method we will cause the linker to delete the reference
+ /// </summary>
+ static void UnusedCodePath ()
+ {
+ LibraryWithMdb.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdb.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdb.cs
new file mode 100644
index 000000000..fd51cdb07
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdb.cs
@@ -0,0 +1,31 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedSymbols ("LibraryWithPdb.dll")]
+
+ [KeptMemberInAssembly ("LibraryWithPdb.dll", typeof (LibraryWithPdb), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithPdb.dll",typeof (LibraryWithPdb), "NotUsed()")]
+ public class ReferenceWithPdb {
+ static void Main ()
+ {
+ // Use some stuff so that we can verify that the linker output correct results
+ SomeMethod ();
+ LibraryWithPdb.SomeMethod ();
+ }
+
+ [Kept]
+ static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..1749b2e69
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbAndSymbolLinkingEnabled.cs
@@ -0,0 +1,35 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")]
+ [SetupLinkerLinkSymbols( "true")]
+
+#if WIN32
+ [KeptSymbols ("LibraryWithPdb.dll")]
+#else
+ [RemovedSymbols ("LibraryWithPdb.dll")]
+#endif
+ [KeptMemberInAssembly ("LibraryWithPdb.dll", typeof (LibraryWithPdb), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithPdb.dll", typeof (LibraryWithPdb), "NotUsed()")]
+ class ReferenceWithPdbAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ // Use some stuff so that we can verify that the linker output correct results
+ SomeMethod();
+ LibraryWithPdb.SomeMethod ();
+ }
+
+ [Kept]
+ static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbCopyAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbCopyAction.cs
new file mode 100644
index 000000000..18e6c817a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbCopyAction.cs
@@ -0,0 +1,18 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")]
+ [SetupLinkerLinkSymbols ("false")]
+ [SetupLinkerAction ("copy", "LibraryWithPdb")]
+
+ [RemovedSymbols ("LibraryWithPdb.dll")]
+ public class ReferenceWithPdbCopyAction {
+ static void Main ()
+ {
+ LibraryWithPdb.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbCopyActionAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbCopyActionAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..b67756bfb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbCopyActionAndSymbolLinkingEnabled.cs
@@ -0,0 +1,18 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")]
+ [SetupLinkerLinkSymbols ("true")]
+ [SetupLinkerAction ("copy", "LibraryWithPdb")]
+
+ [KeptSymbols ("LibraryWithPdb.dll")]
+ public class ReferenceWithPdbCopyActionAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ LibraryWithPdb.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbDeleteAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbDeleteAction.cs
new file mode 100644
index 000000000..8f5e037f8
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbDeleteAction.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedAssembly ("LibraryWithPdb.dll")]
+ [RemovedSymbols ("LibraryWithPdb.dll")]
+ public class ReferenceWithPdbDeleteAction {
+ static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// By not using this method we will cause the linker to delete the reference
+ /// </summary>
+ static void UnusedCodePath ()
+ {
+ LibraryWithPdb.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbDeleteActionAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbDeleteActionAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..44b3df38c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPdbDeleteActionAndSymbolLinkingEnabled.cs
@@ -0,0 +1,25 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")]
+ [SetupLinkerLinkSymbols ("true")]
+
+ [RemovedAssembly ("LibraryWithPdb.dll")]
+ [RemovedSymbols ("LibraryWithPdb.dll")]
+ public class ReferenceWithPdbDeleteActionAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// By not using this method we will cause the linker to delete the reference
+ /// </summary>
+ static void UnusedCodePath ()
+ {
+ LibraryWithPdb.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdb.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdb.cs
new file mode 100644
index 000000000..cb16c5dd1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdb.cs
@@ -0,0 +1,20 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedSymbols ("LibraryWithPortablePdbSymbols.dll")]
+
+ [KeptMemberInAssembly("LibraryWithPortablePdbSymbols.dll", typeof (LibraryWithPortablePdbSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly("LibraryWithPortablePdbSymbols.dll", typeof (LibraryWithPortablePdbSymbols), "NotUsed()")]
+ class ReferenceWithPortablePdb {
+ static void Main ()
+ {
+ LibraryWithPortablePdbSymbols.SomeMethod ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..dd35d6abc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbAndSymbolLinkingEnabled.cs
@@ -0,0 +1,20 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("true")]
+
+ [KeptSymbols ("LibraryWithPortablePdbSymbols.dll")]
+
+ [KeptMemberInAssembly ("LibraryWithPortablePdbSymbols.dll", typeof (LibraryWithPortablePdbSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithPortablePdbSymbols.dll", typeof (LibraryWithPortablePdbSymbols), "NotUsed()")]
+ class ReferenceWithPortablePdbAndSymbolLinkingEnabled {
+ static void Main()
+ {
+ LibraryWithPortablePdbSymbols.SomeMethod ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyAction.cs
new file mode 100644
index 000000000..2f4e428f2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyAction.cs
@@ -0,0 +1,17 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("false")]
+ [SetupLinkerAction ("copy", "LibraryWithPortablePdbSymbols")]
+
+ [RemovedSymbols ("LibraryWithPortablePdbSymbols.dll")]
+ public class ReferenceWithPortablePdbCopyAction {
+ static void Main ()
+ {
+ LibraryWithPortablePdbSymbols.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..292ed8bc0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled.cs
@@ -0,0 +1,17 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("true")]
+ [SetupLinkerAction ("copy", "LibraryWithPortablePdbSymbols")]
+
+ [KeptSymbols ("LibraryWithPortablePdbSymbols.dll")]
+ public class ReferenceWithPortablePdbCopyActionAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ LibraryWithPortablePdbSymbols.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteAction.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteAction.cs
new file mode 100644
index 000000000..f9382472f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteAction.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedAssembly ("LibraryWithPortablePdbSymbols.dll")]
+ [RemovedSymbols ("LibraryWithPortablePdbSymbols.dll")]
+ public class ReferenceWithPortablePdbDeleteAction {
+ static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// By not using this method we will cause the linker to delete the reference
+ /// </summary>
+ static void UnusedCodePath ()
+ {
+ LibraryWithPortablePdbSymbols.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..3ec76815f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")]
+ [SetupLinkerLinkSymbols ("true")]
+
+ [RemovedAssembly ("LibraryWithPortablePdbSymbols.dll")]
+ [RemovedSymbols ("LibraryWithPortablePdbSymbols.dll")]
+ public class ReferenceWithPortablePdbDeleteActionAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ }
+
+ /// <summary>
+ /// By not using this method we will cause the linker to delete the reference
+ /// </summary>
+ static void UnusedCodePath ()
+ {
+ LibraryWithPortablePdbSymbols.SomeMethod ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypes.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypes.cs
new file mode 100644
index 000000000..7ffcca41c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypes.cs
@@ -0,0 +1,65 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb")]
+
+ [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")]
+
+ [SetupCompileBefore ("LibraryWithCompilerDefaultSymbols.dll", new[] { "Dependencies/LibraryWithCompilerDefaultSymbols.cs" }, additionalArguments: "/debug:full")]
+ [SetupCompileBefore("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")]
+ [SetupCompileBefore("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")]
+
+ [SetupCompileArgument ("/debug:full")]
+ [SetupLinkerLinkSymbols ("false")]
+
+ [RemovedSymbols ("test.exe")]
+ [RemovedSymbols ("LibraryWithMdb.dll")]
+ [RemovedSymbols ("LibraryWithPdb.dll")]
+ [RemovedSymbols ("LibraryWithCompilerDefaultSymbols.dll")]
+ [RemovedSymbols ("LibraryWithEmbeddedPdbSymbols.dll")]
+ [RemovedSymbols ("LibraryWithPortablePdbSymbols.dll")]
+
+
+ [KeptMemberInAssembly ("LibraryWithMdb.dll", typeof (LibraryWithMdb), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithMdb.dll", typeof (LibraryWithMdb), "NotUsed()")]
+
+ [KeptMemberInAssembly ("LibraryWithPdb.dll", typeof (LibraryWithPdb), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithPdb.dll", typeof (LibraryWithPdb), "NotUsed()")]
+
+ [KeptMemberInAssembly ("LibraryWithCompilerDefaultSymbols.dll", typeof (LibraryWithCompilerDefaultSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithCompilerDefaultSymbols.dll", typeof (LibraryWithCompilerDefaultSymbols), "NotUsed()")]
+
+ [KeptMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof(LibraryWithEmbeddedPdbSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof(LibraryWithEmbeddedPdbSymbols), "NotUsed()")]
+
+ [KeptMemberInAssembly ("LibraryWithPortablePdbSymbols.dll", typeof (LibraryWithPortablePdbSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithPortablePdbSymbols.dll", typeof (LibraryWithPortablePdbSymbols), "NotUsed()")]
+ public class ReferencesWithMixedSymbolTypes {
+ static void Main()
+ {
+ // Use some stuff so that we can verify that the linker output correct results
+ SomeMethod ();
+ LibraryWithCompilerDefaultSymbols.SomeMethod ();
+ LibraryWithPdb.SomeMethod ();
+ LibraryWithMdb.SomeMethod ();
+ LibraryWithEmbeddedPdbSymbols.SomeMethod ();
+ LibraryWithPortablePdbSymbols.SomeMethod ();
+ }
+
+ [Kept]
+ static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs b/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs
new file mode 100644
index 000000000..610752051
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Symbols/ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled.cs
@@ -0,0 +1,69 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.Symbols.Dependencies;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.Symbols {
+ [Reference ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithMdb/LibraryWithMdb.dll.mdb")]
+
+ [Reference ("Dependencies/LibraryWithPdb/LibraryWithPdb.dll")]
+ [ReferenceDependency ("Dependencies/LibraryWithPdb/LibraryWithPdb.pdb")]
+
+ [SetupCompileBefore ("LibraryWithCompilerDefaultSymbols.dll", new[] { "Dependencies/LibraryWithCompilerDefaultSymbols.cs" }, additionalArguments: "/debug:full")]
+ [SetupCompileBefore ("LibraryWithPortablePdbSymbols.dll", new[] { "Dependencies/LibraryWithPortablePdbSymbols.cs" }, additionalArguments: "/debug:portable", compilerToUse: "csc")]
+ [SetupCompileBefore ("LibraryWithEmbeddedPdbSymbols.dll", new[] { "Dependencies/LibraryWithEmbeddedPdbSymbols.cs" }, additionalArguments: "/debug:embedded", compilerToUse: "csc")]
+
+ [SetupCompileArgument ("/debug:full")]
+ [SetupLinkerLinkSymbols ("true")]
+
+ [KeptSymbols ("test.exe")]
+ [KeptSymbols ("LibraryWithMdb.dll")]
+#if WIN32
+ [KeptSymbols ("LibraryWithPdb.dll")]
+#else
+ [RemovedSymbols ("LibraryWithPdb.dll")]
+#endif
+ [KeptSymbols ("LibraryWithCompilerDefaultSymbols.dll")]
+ [KeptSymbols ("LibraryWithEmbeddedPdbSymbols.dll")]
+ [KeptSymbols ("LibraryWithPortablePdbSymbols.dll")]
+
+
+ [KeptMemberInAssembly ("LibraryWithMdb.dll", typeof (LibraryWithMdb), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithMdb.dll", typeof (LibraryWithMdb), "NotUsed()")]
+
+ [KeptMemberInAssembly ("LibraryWithPdb.dll", typeof (LibraryWithPdb), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithPdb.dll", typeof (LibraryWithPdb), "NotUsed()")]
+
+ [KeptMemberInAssembly ("LibraryWithCompilerDefaultSymbols.dll", typeof (LibraryWithCompilerDefaultSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithCompilerDefaultSymbols.dll", typeof (LibraryWithCompilerDefaultSymbols), "NotUsed()")]
+
+ [KeptMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof (LibraryWithEmbeddedPdbSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithEmbeddedPdbSymbols.dll", typeof (LibraryWithEmbeddedPdbSymbols), "NotUsed()")]
+
+ [KeptMemberInAssembly ("LibraryWithPortablePdbSymbols.dll", typeof (LibraryWithPortablePdbSymbols), "SomeMethod()")]
+ [RemovedMemberInAssembly ("LibraryWithPortablePdbSymbols.dll", typeof (LibraryWithPortablePdbSymbols), "NotUsed()")]
+ public class ReferencesWithMixedSymbolTypesAndSymbolLinkingEnabled {
+ static void Main ()
+ {
+ // Use some stuff so that we can verify that the linker output correct results
+ SomeMethod ();
+ LibraryWithCompilerDefaultSymbols.SomeMethod ();
+ LibraryWithPdb.SomeMethod ();
+ LibraryWithMdb.SomeMethod ();
+ LibraryWithEmbeddedPdbSymbols.SomeMethod ();
+ LibraryWithPortablePdbSymbols.SomeMethod ();
+ }
+
+ [Kept]
+ static void SomeMethod ()
+ {
+ }
+
+ static void NotUsed ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCheckInitializersByIndex.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCheckInitializersByIndex.cs
new file mode 100644
index 000000000..6f7747398
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCheckInitializersByIndex.cs
@@ -0,0 +1,34 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ public class CanCheckInitializersByIndex {
+ public static void Main ()
+ {
+ Method1 ();
+ Method2 ();
+ }
+
+ [Kept]
+ [KeptInitializerData (0)]
+ [KeptInitializerData (1)]
+ [KeptInitializerData (2)]
+ static void Method1 ()
+ {
+ Helper (new [] {1, 2, 3});
+ Helper (new [] {1, 2, 3, 4});
+ Helper (new [] {3, 4, 5});
+ }
+
+ [Kept]
+ [KeptInitializerData (0)]
+ static void Method2 ()
+ {
+ Helper(new [] {10, 11, 12});
+ }
+
+ [Kept]
+ static void Helper<T> (T [] arr)
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileILAssembly.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileILAssembly.cs
new file mode 100644
index 000000000..2662e8f7d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileILAssembly.cs
@@ -0,0 +1,19 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.TestFramework
+{
+ [Define ("IL_ASSEMBLY_AVAILABLE")]
+ [SetupCompileBefore ("ILAssembly.dll", new [] { "Dependencies/ILAssemblySample.il" })]
+ [KeptMemberInAssembly ("ILAssembly.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.ILAssemblySample", "GiveMeAValue()")]
+ public class CanCompileILAssembly
+ {
+ static void Main ()
+ {
+#if IL_ASSEMBLY_AVAILABLE
+ Console.WriteLine (new Mono.Linker.Tests.Cases.TestFramework.Dependencies.ILAssemblySample ().GiveMeAValue ());
+#endif
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesUsingTypes.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesUsingTypes.cs
new file mode 100644
index 000000000..0bcddb212
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesUsingTypes.cs
@@ -0,0 +1,14 @@
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCompileBefore ("library1.dll", new [] { typeof (CanCompileReferencesUsingTypes_LibSource1), typeof (CanCompileReferencesUsingTypes_LibSource2.Nested1.Nested2) })]
+ public class CanCompileReferencesUsingTypes {
+ public static void Main ()
+ {
+ // Only the compile before assembly types are used because we wouldn't have access to the after types
+ CanCompileReferencesUsingTypes_LibSource1.MethodFromParentType ();
+ CanCompileReferencesUsingTypes_LibSource2.Nested1.Nested2.MethodFromNestedNested ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResources.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResources.cs
new file mode 100644
index 000000000..c55e96a98
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResources.cs
@@ -0,0 +1,24 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCompileBefore ("library.dll",
+ new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.cs" },
+ resources: new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.txt" })]
+
+ // Compile the same assembly again with another resource to get coverage on SetupCompileAfter
+ [SetupCompileAfter ("library.dll",
+ new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.cs" },
+ resources: new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.txt", "Dependencies/CanCompileReferencesWithResources_Lib1.log" })]
+
+ [KeptResourceInAssembly ("library.dll", "CanCompileReferencesWithResources_Lib1.txt")]
+ [KeptResourceInAssembly ("library.dll", "CanCompileReferencesWithResources_Lib1.log")]
+ public class CanCompileReferencesWithResources {
+ public static void Main ()
+ {
+ // Use something so that reference isn't removed at compile time
+ CanCompileReferencesWithResources_Lib1.Used ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResourcesWithCsc.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResourcesWithCsc.cs
new file mode 100644
index 000000000..75e85d8b7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResourcesWithCsc.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCompileBefore ("library.dll",
+ new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.cs" },
+ resources: new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.txt" },
+ compilerToUse: "csc")]
+
+ // Compile the same assembly again with another resource to get coverage on SetupCompileAfter
+ [SetupCompileAfter ("library.dll",
+ new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.cs" },
+ resources: new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.txt", "Dependencies/CanCompileReferencesWithResources_Lib1.log" },
+ compilerToUse: "csc")]
+
+ [KeptResourceInAssembly ("library.dll", "CanCompileReferencesWithResources_Lib1.txt")]
+ [KeptResourceInAssembly ("library.dll", "CanCompileReferencesWithResources_Lib1.log")]
+ public class CanCompileReferencesWithResourcesWithCsc {
+ public static void Main ()
+ {
+ // Use something so that reference isn't removed at compile time
+ CanCompileReferencesWithResources_Lib1.Used ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResourcesWithMcs.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResourcesWithMcs.cs
new file mode 100644
index 000000000..42fa53931
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileReferencesWithResourcesWithMcs.cs
@@ -0,0 +1,26 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCompileBefore ("library.dll",
+ new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.cs" },
+ resources: new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.txt" },
+ compilerToUse: "mcs")]
+
+ // Compile the same assembly again with another resource to get coverage on SetupCompileAfter
+ [SetupCompileAfter ("library.dll",
+ new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.cs" },
+ resources: new [] { "Dependencies/CanCompileReferencesWithResources_Lib1.txt", "Dependencies/CanCompileReferencesWithResources_Lib1.log" },
+ compilerToUse: "mcs")]
+
+ [KeptResourceInAssembly ("library.dll", "CanCompileReferencesWithResources_Lib1.txt")]
+ [KeptResourceInAssembly ("library.dll", "CanCompileReferencesWithResources_Lib1.log")]
+ public class CanCompileReferencesWithResourcesWithMcs {
+ public static void Main ()
+ {
+ // Use something so that reference isn't removed at compile time
+ CanCompileReferencesWithResources_Lib1.Used ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithCsc.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithCsc.cs
new file mode 100644
index 000000000..5ecaea8aa
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithCsc.cs
@@ -0,0 +1,39 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCSharpCompilerToUse ("csc")]
+
+ // Use all of the compiler setup attributes so that we can verify they all work
+ // when roslyn is used
+ [SetupCompileArgument ("/debug:portable")]
+ [SetupCompileResource ("Dependencies/CanCompileTestCaseWithCsc.txt")]
+ [Define ("VERIFY_DEFINE_WORKS")]
+ [Reference ("System.dll")]
+
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/CanCompileTestCaseWithCsc_Lib.cs" }, compilerToUse: "csc")]
+
+ [KeptResource ("CanCompileTestCaseWithCsc.txt")]
+ [KeptMemberInAssembly ("library.dll", typeof (CanCompileTestCaseWithCsc_Lib), "Used()")]
+ class CanCompileTestCaseWithCsc {
+ static void Main ()
+ {
+#if VERIFY_DEFINE_WORKS
+ UsedByDefine ();
+#endif
+ // Use something from System.dll so that we can verify the reference attribute works
+ var timer = new System.Timers.Timer ();
+
+ CanCompileTestCaseWithCsc_Lib.Used ();
+ }
+
+ [Kept]
+ static void UsedByDefine ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithDebugPdbs.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithDebugPdbs.cs
new file mode 100644
index 000000000..22e6525c1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithDebugPdbs.cs
@@ -0,0 +1,25 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+// Because we compiled with debug information, this attribute should exist
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCompileArgument ("/debug:pdbonly")]
+ class CanCompileTestCaseWithDebugPdbs {
+ static void Main ()
+ {
+ new Foo ().Method ();
+ }
+
+ [Kept]
+ [KeptMember (".ctor()")]
+ class Foo {
+ [Kept]
+ public void Method ()
+ {
+ }
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithMsc.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithMsc.cs
new file mode 100644
index 000000000..7bafdc3d2
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanCompileTestCaseWithMsc.cs
@@ -0,0 +1,39 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+[assembly: KeptAttributeAttribute (typeof (System.Diagnostics.DebuggableAttribute))]
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCSharpCompilerToUse ("mcs")]
+
+ // Use all of the compiler setup attributes so that we can verify they all work
+ // when roslyn is used
+ [SetupCompileArgument ("/debug:pdbonly")]
+ [SetupCompileResource ("Dependencies/CanCompileTestCaseWithMcs.txt")]
+ [Define ("VERIFY_DEFINE_WORKS")]
+ [Reference ("System.dll")]
+
+ [SetupCompileBefore ("library.dll", new[] { "Dependencies/CanCompileTestCaseWithMcs_Lib.cs" }, compilerToUse: "mcs")]
+
+ [KeptResource ("CanCompileTestCaseWithMcs.txt")]
+ [KeptMemberInAssembly ("library.dll", typeof (CanCompileTestCaseWithMcs_Lib), "Used()")]
+ class CanCompileTestCaseWithMsc {
+ static void Main ()
+ {
+#if VERIFY_DEFINE_WORKS
+ UsedByDefine ();
+#endif
+ // Use something from System.dll so that we can verify the reference attribute works
+ var timer = new System.Timers.Timer ();
+
+ CanCompileTestCaseWithMcs_Lib.Used ();
+ }
+
+ [Kept]
+ static void UsedByDefine ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanSandboxDependenciesUsingType.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanSandboxDependenciesUsingType.cs
new file mode 100644
index 000000000..baa322be1
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanSandboxDependenciesUsingType.cs
@@ -0,0 +1,14 @@
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SandboxDependency (typeof (CanSandboxDependenciesUsingType_Source1))]
+ [SandboxDependency (typeof (CanSandboxDependenciesUsingType_Source2.Nested1.Nested2), "NameChanged.cs")]
+ public class CanSandboxDependenciesUsingType {
+ public static void Main ()
+ {
+ CanSandboxDependenciesUsingType_Source1.Method ();
+ CanSandboxDependenciesUsingType_Source2.Nested1.Nested2.Method ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/CanVerifyInterfacesOnTypesInAssembly.cs b/test/Mono.Linker.Tests.Cases/TestFramework/CanVerifyInterfacesOnTypesInAssembly.cs
new file mode 100644
index 000000000..964d5e779
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/CanVerifyInterfacesOnTypesInAssembly.cs
@@ -0,0 +1,16 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCompileBefore ("library.dll", new [] {"Dependencies/CanVerifyInterfacesOnTypesInAssembly_Lib.cs"})]
+ [KeptInterfaceOnTypeInAssembly ("library", typeof (CanVerifyInterfacesOnTypesInAssembly_Lib.A), "library", typeof (CanVerifyInterfacesOnTypesInAssembly_Lib.IFoo))]
+ [RemovedInterfaceOnTypeInAssembly ("library", typeof (CanVerifyInterfacesOnTypesInAssembly_Lib.A), "library", typeof (CanVerifyInterfacesOnTypesInAssembly_Lib.IBar))]
+ public class CanVerifyInterfacesOnTypesInAssembly {
+ public static void Main ()
+ {
+ CanVerifyInterfacesOnTypesInAssembly_Lib.IFoo a = new CanVerifyInterfacesOnTypesInAssembly_Lib.A ();
+ a.Foo ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesUsingTypes_LibSource1.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesUsingTypes_LibSource1.cs
new file mode 100644
index 000000000..01e15ec32
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesUsingTypes_LibSource1.cs
@@ -0,0 +1,7 @@
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ public class CanCompileReferencesUsingTypes_LibSource1 {
+ public static void MethodFromParentType ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesUsingTypes_LibSource2.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesUsingTypes_LibSource2.cs
new file mode 100644
index 000000000..b9c983b77
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesUsingTypes_LibSource2.cs
@@ -0,0 +1,11 @@
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ public class CanCompileReferencesUsingTypes_LibSource2 {
+ public class Nested1 {
+ public class Nested2 {
+ public static void MethodFromNestedNested ()
+ {
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.cs
new file mode 100644
index 000000000..358cd3c42
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.cs
@@ -0,0 +1,7 @@
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ public class CanCompileReferencesWithResources_Lib1 {
+ public static void Used ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.log b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.log
new file mode 100644
index 000000000..b27f91d6f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.log
@@ -0,0 +1 @@
+Hello
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.txt b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.txt
new file mode 100644
index 000000000..5ab2f8a43
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileReferencesWithResources_Lib1.txt
@@ -0,0 +1 @@
+Hello \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithCsc.txt b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithCsc.txt
new file mode 100644
index 000000000..540b7baa7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithCsc.txt
@@ -0,0 +1 @@
+Resource that is kept \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithCsc_Lib.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithCsc_Lib.cs
new file mode 100644
index 000000000..120b2d367
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithCsc_Lib.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ public class CanCompileTestCaseWithCsc_Lib {
+ public static void Used ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithMcs.txt b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithMcs.txt
new file mode 100644
index 000000000..540b7baa7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithMcs.txt
@@ -0,0 +1 @@
+Resource that is kept \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithMcs_Lib.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithMcs_Lib.cs
new file mode 100644
index 000000000..09b05174c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanCompileTestCaseWithMcs_Lib.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ public class CanCompileTestCaseWithMcs_Lib {
+ public static void Used ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanSandboxDependenciesUsingType_Source1.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanSandboxDependenciesUsingType_Source1.cs
new file mode 100644
index 000000000..ada073096
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanSandboxDependenciesUsingType_Source1.cs
@@ -0,0 +1,11 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ [Kept]
+ public class CanSandboxDependenciesUsingType_Source1 {
+ [Kept]
+ public static void Method ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanSandboxDependenciesUsingType_Source2.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanSandboxDependenciesUsingType_Source2.cs
new file mode 100644
index 000000000..2a730074f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanSandboxDependenciesUsingType_Source2.cs
@@ -0,0 +1,17 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ [Kept]
+ public class CanSandboxDependenciesUsingType_Source2 {
+ [Kept]
+ public class Nested1 {
+ [Kept]
+ public class Nested2 {
+ [Kept]
+ public static void Method ()
+ {
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanVerifyInterfacesOnTypesInAssembly_Lib.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanVerifyInterfacesOnTypesInAssembly_Lib.cs
new file mode 100644
index 000000000..06aa2f050
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/CanVerifyInterfacesOnTypesInAssembly_Lib.cs
@@ -0,0 +1,20 @@
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ public class CanVerifyInterfacesOnTypesInAssembly_Lib {
+ public interface IFoo {
+ void Foo ();
+ }
+ public interface IBar {
+ void Bar ();
+ }
+
+ public class A : IFoo, IBar {
+ public void Foo ()
+ {
+ }
+
+ public void Bar ()
+ {
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/ILAssemblySample.il b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/ILAssemblySample.il
new file mode 100644
index 000000000..0060542bd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/ILAssemblySample.il
@@ -0,0 +1,42 @@
+.assembly extern mscorlib
+{
+}
+
+.assembly ILAssembly
+{
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+
+.module ILAssembly.dll
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public auto ansi beforefieldinit Mono.Linker.Tests.Cases.TestFramework.Dependencies.ILAssemblySample
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method ILAssemblySample::.ctor
+
+ .method public hidebysig instance string
+ GiveMeAValue() cil managed
+ {
+ .maxstack 1
+ .locals init (string V_0)
+ IL_0000: nop
+ IL_0001: ldstr "Bar"
+ IL_0006: stloc.0
+ IL_0007: br IL_000c
+
+ IL_000c: ldloc.0
+ IL_000d: ret
+ } // end of method ILAssemblySample::GiveMeAValue
+
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyAttributesInAssemblyWorks_Base.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyAttributesInAssemblyWorks_Base.cs
new file mode 100644
index 000000000..92eb9ef8a
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyAttributesInAssemblyWorks_Base.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ public class VerifyAttributesInAssemblyWorks_Base {
+ public class ForAssertingKeptAttribute : Attribute {
+ }
+
+ public class ForAssertingRemoveAttribute : Attribute {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyAttributesInAssemblyWorks_Lib.cs b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyAttributesInAssemblyWorks_Lib.cs
new file mode 100644
index 000000000..57dd0c380
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyAttributesInAssemblyWorks_Lib.cs
@@ -0,0 +1,37 @@
+
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+[assembly: VerifyAttributesInAssemblyWorks_Base.ForAssertingKept]
+[assembly: VerifyAttributesInAssemblyWorks_Base.ForAssertingRemove]
+
+namespace Mono.Linker.Tests.Cases.TestFramework.Dependencies {
+ public class VerifyAttributesInAssemblyWorks_Lib {
+ [VerifyAttributesInAssemblyWorks_Base.ForAssertingKept]
+ public static class TypeWithKeptAttribute {
+ [VerifyAttributesInAssemblyWorks_Base.ForAssertingKept]
+ public static int Field;
+
+ [VerifyAttributesInAssemblyWorks_Base.ForAssertingKept]
+ public static void Method ()
+ {
+ }
+
+ [VerifyAttributesInAssemblyWorks_Base.ForAssertingKept]
+ public static int Property { get; set; }
+ }
+
+ [VerifyAttributesInAssemblyWorks_Base.ForAssertingRemove]
+ public class TypeWithRemovedAttribute {
+ [VerifyAttributesInAssemblyWorks_Base.ForAssertingRemove]
+ public static int Field;
+
+ [VerifyAttributesInAssemblyWorks_Base.ForAssertingRemove]
+ public static void Method ()
+ {
+ }
+
+ [VerifyAttributesInAssemblyWorks_Base.ForAssertingRemove]
+ public static int Property { get; set; }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyResourceInAssemblyAttributesBehavior.txt b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyResourceInAssemblyAttributesBehavior.txt
new file mode 100644
index 000000000..540b7baa7
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/Dependencies/VerifyResourceInAssemblyAttributesBehavior.txt
@@ -0,0 +1 @@
+Resource that is kept \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/VerifyAttributesInAssemblyWorks.cs b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyAttributesInAssemblyWorks.cs
new file mode 100644
index 000000000..ae450e2a5
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyAttributesInAssemblyWorks.cs
@@ -0,0 +1,38 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ // Put the attribute types in a different assembly than where we will assert since that is a more complex use case
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/VerifyAttributesInAssemblyWorks_Base.cs" })]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/VerifyAttributesInAssemblyWorks_Lib.cs" }, new [] { "base.dll" })]
+
+ [KeptAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingKeptAttribute))]
+ [KeptAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingKeptAttribute), typeof (VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute))]
+ [KeptAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingKeptAttribute), typeof (VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute), "Field")]
+ [KeptAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingKeptAttribute), typeof (VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute), "Property")]
+ [KeptAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingKeptAttribute), typeof (VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute), "Method()")]
+
+ [RemovedAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingRemoveAttribute))]
+ [RemovedAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingRemoveAttribute), typeof (VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute))]
+ [RemovedAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingRemoveAttribute), typeof (VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute), "Field")]
+ [RemovedAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingRemoveAttribute), typeof (VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute), "Property")]
+ [RemovedAttributeInAssembly ("library.dll", typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingRemoveAttribute), typeof (VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute), "Method()")]
+ public class VerifyAttributesInAssemblyWorks {
+ public static void Main ()
+ {
+ // Use the attribute type we want to keep
+ var tmp = typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingKeptAttribute).ToString ();
+
+ // Now use the members of both types
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute.Field = 1;
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute.Property = 1;
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute.Method ();
+
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute.Field = 1;
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute.Property = 1;
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute.Method ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/VerifyAttributesInAssemblyWorksWithStrings.cs b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyAttributesInAssemblyWorksWithStrings.cs
new file mode 100644
index 000000000..bf1e0f18f
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyAttributesInAssemblyWorksWithStrings.cs
@@ -0,0 +1,38 @@
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TestFramework.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupLinkerArgument ("--used-attrs-only", "true")]
+ // Put the attribute types in a different assembly than where we will assert since that is a more complex use case
+ [SetupCompileBefore ("base.dll", new [] { "Dependencies/VerifyAttributesInAssemblyWorks_Base.cs"} )]
+ [SetupCompileBefore ("library.dll", new [] { "Dependencies/VerifyAttributesInAssemblyWorks_Lib.cs"}, new [] { "base.dll" })]
+
+ [KeptAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingKeptAttribute")]
+ [KeptAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingKeptAttribute", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Lib/TypeWithKeptAttribute")]
+ [KeptAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingKeptAttribute", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Lib/TypeWithKeptAttribute", "Field")]
+ [KeptAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingKeptAttribute", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Lib/TypeWithKeptAttribute", "Property")]
+ [KeptAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingKeptAttribute", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Lib/TypeWithKeptAttribute", "Method()")]
+
+ [RemovedAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingRemoveAttribute")]
+ [RemovedAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingRemoveAttribute", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Lib/TypeWithRemovedAttribute")]
+ [RemovedAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingRemoveAttribute", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Lib/TypeWithRemovedAttribute", "Field")]
+ [RemovedAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingRemoveAttribute", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Lib/TypeWithRemovedAttribute", "Property")]
+ [RemovedAttributeInAssembly ("library.dll", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Base/ForAssertingRemoveAttribute", "Mono.Linker.Tests.Cases.TestFramework.Dependencies.VerifyAttributesInAssemblyWorks_Lib/TypeWithRemovedAttribute", "Method()")]
+ public class VerifyAttributesInAssemblyWorksWithStrings {
+ public static void Main ()
+ {
+ // Use the attribute type we want to keep
+ var tmp = typeof (VerifyAttributesInAssemblyWorks_Base.ForAssertingKeptAttribute).ToString ();
+
+ // Now use the members of both types
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute.Field = 1;
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute.Property = 1;
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithKeptAttribute.Method ();
+
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute.Field = 1;
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute.Property = 1;
+ VerifyAttributesInAssemblyWorks_Lib.TypeWithRemovedAttribute.Method ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/VerifyDefineAttributeBehavior.cs b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyDefineAttributeBehavior.cs
new file mode 100644
index 000000000..abe143042
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyDefineAttributeBehavior.cs
@@ -0,0 +1,26 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+
+ /// <summary>
+ /// The purpose of this test is to verify that the testing framework's define attribute is working correctly
+ /// </summary>
+ [Define("SOME_DEFINE")]
+ public class VerifyDefineAttributeBehavior {
+ static void Main ()
+ {
+#if SOME_DEFINE
+ MethodThatIsUsedIfDefineIsWorkingProperly ();
+#endif
+ }
+
+
+ [Kept]
+ static void MethodThatIsUsedIfDefineIsWorkingProperly ()
+ {
+ Console.WriteLine ("Foo");
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/VerifyExpectModifiedAttributesWork.cs b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyExpectModifiedAttributesWork.cs
new file mode 100644
index 000000000..2cd46fc79
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyExpectModifiedAttributesWork.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Diagnostics.Tracing;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ /// <summary>
+ /// This test is here to give some coverage to the attribute to ensure it doesn't break. We need to leverage the ETW feature since it is the only
+ /// one that modifies bodies currently
+ /// </summary>
+ [SetupLinkerArgument ("--exclude-feature", "etw")]
+ // Used to avoid different compilers generating different IL which can mess up the instruction asserts
+ [SetupCompileArgument ("/optimize+")]
+ public class VerifyExpectModifiedAttributesWork {
+ public static void Main ()
+ {
+ var b = VerifyExpectModifiedAttributesWork_RemovedEventSource.Log.IsEnabled ();
+ if (b)
+ VerifyExpectModifiedAttributesWork_RemovedEventSource.Log.SomeMethod ();
+ }
+
+ public class ClassForLocal {
+ }
+
+ public static void CallsToForceALocal (int arg1, int arg2, int arg3)
+ {
+ }
+ }
+
+ [Kept]
+ [KeptBaseType (typeof (EventSource))]
+ [KeptMember (".ctor()")]
+ [KeptMember (".cctor()")]
+ [EventSource (Name = "MyCompany")]
+ class VerifyExpectModifiedAttributesWork_RemovedEventSource : EventSource {
+ public class Keywords {
+ public const EventKeywords Page = (EventKeywords)1;
+
+ public int Unused;
+ }
+
+ [Kept]
+ public static VerifyExpectModifiedAttributesWork_RemovedEventSource Log = new VerifyExpectModifiedAttributesWork_RemovedEventSource ();
+
+ [Kept]
+ [ExpectBodyModified]
+ [ExpectExceptionHandlersModified]
+ [ExpectLocalsModified]
+ protected override void OnEventCommand (EventCommandEventArgs command)
+ {
+ try {
+ // Do some extra stuff to be extra certain the compiler introduced a local instead of using `dup`
+ var tmp = new VerifyExpectModifiedAttributesWork.ClassForLocal ();
+ VerifyExpectModifiedAttributesWork.CallsToForceALocal (1, 3, 4);
+ VerifyExpectModifiedAttributesWork.CallsToForceALocal (1, 4, 4);
+ var hashcode = tmp.GetHashCode ();
+ VerifyExpectModifiedAttributesWork.CallsToForceALocal(1, hashcode, 3);
+ } catch {
+ try {
+ Removed ();
+ } catch {
+ var tmp = new VerifyExpectModifiedAttributesWork.ClassForLocal ();
+ VerifyExpectModifiedAttributesWork.CallsToForceALocal (1, 3, 4);
+ VerifyExpectModifiedAttributesWork.CallsToForceALocal (1, 4, 4);
+ var hashcode = tmp.GetHashCode ();
+ VerifyExpectModifiedAttributesWork.CallsToForceALocal(1, hashcode, 3);
+ throw;
+ }
+ throw;
+ }
+ }
+
+ [Kept]
+ [Event (8)]
+ [ExpectBodyModified]
+ public void SomeMethod ()
+ {
+ Removed ();
+ }
+
+ public void Removed ()
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TestFramework/VerifyResourceInAssemblyAttributesBehavior.cs b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyResourceInAssemblyAttributesBehavior.cs
new file mode 100644
index 000000000..c54be7565
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TestFramework/VerifyResourceInAssemblyAttributesBehavior.cs
@@ -0,0 +1,18 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.TestFramework {
+ [SetupCompileResource ("Dependencies/VerifyResourceInAssemblyAttributesBehavior.txt")]
+ [KeptResource ("VerifyResourceInAssemblyAttributesBehavior.txt")]
+ // These are technically redundant, but the goal of this test is to verify the attributes are working which we can do
+ // by using them on the test case assembly even though you would normally use these attributes for other checking other
+ // supporting assemblies
+ [KeptResourceInAssembly ("test.exe", "VerifyResourceInAssemblyAttributesBehavior.txt")]
+ [RemovedResourceInAssembly ("test.exe", "NeverExistedResource.txt")]
+ public class VerifyResourceInAssemblyAttributesBehavior {
+ public static void Main ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanDumpDependenciesToUncompressedXml.cs b/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanDumpDependenciesToUncompressedXml.cs
new file mode 100644
index 000000000..5e4d82e8e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanDumpDependenciesToUncompressedXml.cs
@@ -0,0 +1,13 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Tracing.Individual {
+
+ [SetupLinkerArgument ("--dump-dependencies")]
+ [SetupLinkerArgument ("--dependencies-file", "linker-dependencies.xml")]
+ public class CanDumpDependenciesToUncompressedXml {
+ public static void Main ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanEnableDependenciesDump.cs b/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanEnableDependenciesDump.cs
new file mode 100644
index 000000000..810023860
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanEnableDependenciesDump.cs
@@ -0,0 +1,12 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Tracing.Individual {
+
+ [SetupLinkerArgument ("--dump-dependencies")]
+ public class CanEnableDependenciesDump {
+ public static void Main ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanEnableReducedTracing.cs b/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanEnableReducedTracing.cs
new file mode 100644
index 000000000..cc91dc1dc
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/Tracing/Individual/CanEnableReducedTracing.cs
@@ -0,0 +1,16 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.Tracing.Individual {
+
+ [SetupLinkerArgument ("--dump-dependencies")]
+ [SetupLinkerArgument ("--reduced-tracing", "true")]
+
+ // Need to define a custom name so that the linker outputs in uncompressed format, which is more useful for making assertions
+ [SetupLinkerArgument ("--dependencies-file", "linker-dependencies.xml")]
+ public class CanEnableReducedTracing {
+ public static void Main ()
+ {
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ForwarderLibrary.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ForwarderLibrary.cs
new file mode 100644
index 000000000..bb1521525
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ForwarderLibrary.cs
@@ -0,0 +1,3 @@
+using System;
+
+[assembly: System.Runtime.CompilerServices.TypeForwardedTo (typeof (Mono.Linker.Tests.Cases.TypeForwarding.Dependencies.ImplementationLibrary))]
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ImplementationLibrary.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ImplementationLibrary.cs
new file mode 100644
index 000000000..35c2252f4
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ImplementationLibrary.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Reflection;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+[assembly: AssemblyVersion ("2.0")]
+
+namespace Mono.Linker.Tests.Cases.TypeForwarding.Dependencies {
+ public class ImplementationLibrary {
+ public string GetSomeValue ()
+ {
+ return "Hello";
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/LibraryUsingForwarder.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/LibraryUsingForwarder.cs
new file mode 100644
index 000000000..97c728e7d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/LibraryUsingForwarder.cs
@@ -0,0 +1,12 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.TypeForwarding.Dependencies {
+ [NotATestCase]
+ public class LibraryUsingForwarder {
+ public string GetValueFromOtherAssembly ()
+ {
+ return new ImplementationLibrary ().GetSomeValue ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ReferenceImplementationLibrary.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ReferenceImplementationLibrary.cs
new file mode 100644
index 000000000..00bb1e30c
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/ReferenceImplementationLibrary.cs
@@ -0,0 +1,17 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.TypeForwarding.Dependencies {
+ [NotATestCase]
+ public class ReferenceImplementationLibrary {
+ }
+
+#if INCLUDE_REFERENCE_IMPL
+ public class ImplementationLibrary {
+ public string GetSomeValue ()
+ {
+ return null;
+ }
+ }
+#endif
+}
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/TypeForwarderMissingReference.il b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/TypeForwarderMissingReference.il
new file mode 100644
index 000000000..0f8a1e93d
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/Dependencies/TypeForwarderMissingReference.il
@@ -0,0 +1,37 @@
+.assembly extern mscorlib
+{
+}
+.assembly extern 'missing-reference'
+{
+ .ver 0:0:0:0
+}
+
+.assembly 'TypeForwarderMissingReference'
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+
+.class extern forwarder C
+{
+ .assembly extern 'missing-reference'
+}
+.class extern forwarder G`1
+{
+ .assembly extern 'missing-reference'
+}
+
+.module 'TypeForwarderMissingReference.dll'
+
+
+.class public auto ansi beforefieldinit DummyClass
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/MissingTargetReference.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/MissingTargetReference.cs
new file mode 100644
index 000000000..5e8b11571
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/MissingTargetReference.cs
@@ -0,0 +1,24 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.TypeForwarding
+{
+ [SkipUnresolved (true)]
+ [Define ("IL_ASSEMBLY_AVAILABLE")]
+ [SetupCompileBefore ("TypeForwarderMissingReference.dll", new [] { "Dependencies/TypeForwarderMissingReference.il" })]
+ [SetupLinkerAction ("link", "TypeForwarderMissingReference.dll")]
+
+ [KeptMemberInAssembly ("TypeForwarderMissingReference.dll", "DummyClass", ".ctor()")]
+ [RemovedForwarder ("TypeForwarderMissingReference.dll", "C")]
+ [RemovedForwarder ("TypeForwarderMissingReference.dll", "G<>")]
+ public class MissingTargetReference
+ {
+ public static void Main ()
+ {
+#if IL_ASSEMBLY_AVAILABLE
+ Console.WriteLine (new DummyClass ());
+#endif
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssembliesKept.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssembliesKept.cs
new file mode 100644
index 000000000..e8a41a259
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssembliesKept.cs
@@ -0,0 +1,26 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TypeForwarding {
+ [KeepTypeForwarderOnlyAssemblies ("true")]
+ [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })]
+ // Add another assembly in that uses the forwarder just to make things a little more complex
+ [SetupCompileBefore ("Library.dll", new[] { "Dependencies/LibraryUsingForwarder.cs" }, references: new[] { "Forwarder.dll" })]
+
+ // After compiling the test case we then replace the reference impl with implementation + type forwarder
+ [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })]
+ [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })]
+
+ [KeptAssembly ("Forwarder.dll")]
+ [KeptMemberInAssembly ("Library.dll", typeof (LibraryUsingForwarder), "GetValueFromOtherAssembly()")]
+ [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")]
+ public class TypeForwarderOnlyAssembliesKept {
+ public static void Main ()
+ {
+ Console.WriteLine (new ImplementationLibrary ().GetSomeValue ());
+ Console.WriteLine (new LibraryUsingForwarder ().GetValueFromOtherAssembly ());
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssembliesRemoved.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssembliesRemoved.cs
new file mode 100644
index 000000000..91ddd58ee
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssembliesRemoved.cs
@@ -0,0 +1,27 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TypeForwarding
+{
+ [KeepTypeForwarderOnlyAssemblies ("false")]
+ [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })]
+ // Add another assembly in that uses the forwarder just to make things a little more complex
+ [SetupCompileBefore ("Library.dll", new[] { "Dependencies/LibraryUsingForwarder.cs" }, references: new[] { "Forwarder.dll" })]
+
+ // After compiling the test case we then replace the reference impl with implementation + type forwarder
+ [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })]
+ [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })]
+
+ [RemovedAssembly ("Forwarder.dll")]
+ [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")]
+ [KeptMemberInAssembly ("Library.dll", typeof (LibraryUsingForwarder), "GetValueFromOtherAssembly()")]
+ class TypeForwarderOnlyAssembliesRemoved {
+ static void Main()
+ {
+ Console.WriteLine (new ImplementationLibrary ().GetSomeValue ());
+ Console.WriteLine (new LibraryUsingForwarder ().GetValueFromOtherAssembly ());
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.cs b/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.cs
new file mode 100644
index 000000000..95a0ad138
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.cs
@@ -0,0 +1,28 @@
+using System;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Cases.TypeForwarding.Dependencies;
+
+namespace Mono.Linker.Tests.Cases.TypeForwarding {
+ [KeepTypeForwarderOnlyAssemblies ("false")]
+ [SetupCompileBefore ("Forwarder.dll", new[] { "Dependencies/ReferenceImplementationLibrary.cs" }, defines: new[] { "INCLUDE_REFERENCE_IMPL" })]
+ // Add another assembly in that uses the forwarder just to make things a little more complex
+ [SetupCompileBefore ("Library.dll", new[] { "Dependencies/LibraryUsingForwarder.cs" }, references: new[] { "Forwarder.dll" })]
+
+ // After compiling the test case we then replace the reference impl with implementation + type forwarder
+ [SetupCompileAfter ("Implementation.dll", new[] { "Dependencies/ImplementationLibrary.cs" })]
+ [SetupCompileAfter ("Forwarder.dll", new[] { "Dependencies/ForwarderLibrary.cs" }, references: new[] { "Implementation.dll" })]
+
+ [KeptAssembly ("Forwarder.dll")]
+ [KeptMemberInAssembly ("Implementation.dll", typeof (ImplementationLibrary), "GetSomeValue()")]
+ [KeptMemberInAssembly ("Library.dll", typeof (LibraryUsingForwarder), "GetValueFromOtherAssembly()")]
+
+ [KeptTypeInAssembly("Forwarder.dll", typeof (ImplementationLibrary))]
+ public class TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml {
+ static void Main()
+ {
+ Console.WriteLine (new ImplementationLibrary ().GetSomeValue ());
+ Console.WriteLine (new LibraryUsingForwarder ().GetValueFromOtherAssembly ());
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.xml b/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.xml
new file mode 100644
index 000000000..28d5c08cd
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/TypeForwarding/TypeForwarderOnlyAssemblyCanBePreservedViaLinkXml.xml
@@ -0,0 +1,4 @@
+<linker>
+ <assembly fullname="Forwarder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
+ </assembly>
+</linker> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/Extensions/CecilExtensions.cs b/test/Mono.Linker.Tests/Extensions/CecilExtensions.cs
new file mode 100644
index 000000000..747abf570
--- /dev/null
+++ b/test/Mono.Linker.Tests/Extensions/CecilExtensions.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Mono.Cecil;
+
+namespace Mono.Linker.Tests.Extensions {
+ public static class CecilExtensions {
+ public static IEnumerable<TypeDefinition> AllDefinedTypes (this AssemblyDefinition assemblyDefinition)
+ {
+ return assemblyDefinition.Modules.SelectMany (m => m.AllDefinedTypes ());
+ }
+
+ public static IEnumerable<TypeDefinition> AllDefinedTypes (this ModuleDefinition moduleDefinition)
+ {
+ foreach (var typeDefinition in moduleDefinition.Types) {
+ yield return typeDefinition;
+
+ foreach (var definition in typeDefinition.AllDefinedTypes ())
+ yield return definition;
+ }
+ }
+
+ public static IEnumerable<TypeDefinition> AllDefinedTypes (this TypeDefinition typeDefinition)
+ {
+ foreach (var nestedType in typeDefinition.NestedTypes) {
+ yield return nestedType;
+
+ foreach (var definition in nestedType.AllDefinedTypes ())
+ yield return definition;
+ }
+ }
+
+ public static IEnumerable<IMemberDefinition> AllMembers (this ModuleDefinition module)
+ {
+ foreach (var type in module.AllDefinedTypes ()) {
+ yield return type;
+
+ foreach (var member in type.AllMembers ())
+ yield return member;
+ }
+ }
+
+ public static IEnumerable<IMemberDefinition> AllMembers (this TypeDefinition type)
+ {
+ foreach (var field in type.Fields)
+ yield return field;
+
+ foreach (var prop in type.Properties)
+ yield return prop;
+
+ foreach (var method in type.Methods)
+ yield return method;
+
+ foreach (var @event in type.Events)
+ yield return @event;
+ }
+
+ public static bool HasAttribute (this ICustomAttributeProvider provider, string name)
+ {
+ return provider.CustomAttributes.Any (ca => ca.AttributeType.Name == name);
+ }
+
+ public static bool HasAttributeDerivedFrom (this ICustomAttributeProvider provider, string name)
+ {
+ return provider.CustomAttributes.Any (ca => ca.AttributeType.Resolve ().DerivesFrom (name));
+ }
+
+ public static bool DerivesFrom (this TypeDefinition type, string baseTypeName)
+ {
+ if (type.Name == baseTypeName)
+ return true;
+
+ if (type.BaseType == null)
+ return false;
+
+ if (type.BaseType.Name == baseTypeName)
+ return true;
+
+ return type.BaseType.Resolve ().DerivesFrom (baseTypeName);
+ }
+
+ public static PropertyDefinition GetPropertyDefinition (this MethodDefinition method)
+ {
+ if (!method.IsSetter && !method.IsGetter)
+ throw new ArgumentException ();
+
+ var propertyName = method.Name.Substring (4);
+ return method.DeclaringType.Properties.First (p => p.Name == propertyName);
+ }
+
+ public static string GetSignature (this MethodDefinition method)
+ {
+ var builder = new StringBuilder ();
+ builder.Append (method.Name);
+ if (method.HasGenericParameters) {
+ builder.Append ('<');
+
+ for (int i = 0; i < method.GenericParameters.Count - 1; i++)
+ builder.Append ($"{method.GenericParameters [i]},");
+
+ builder.Append ($"{method.GenericParameters [method.GenericParameters.Count - 1]}>");
+ }
+
+ builder.Append ("(");
+
+ if (method.HasParameters) {
+ for (int i = 0; i < method.Parameters.Count - 1; i++) {
+ // TODO: modifiers
+ // TODO: default values
+ builder.Append ($"{method.Parameters [i].ParameterType},");
+ }
+
+ builder.Append (method.Parameters [method.Parameters.Count - 1].ParameterType);
+ }
+
+ builder.Append (")");
+
+ return builder.ToString ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/Extensions/NiceIO.cs b/test/Mono.Linker.Tests/Extensions/NiceIO.cs
new file mode 100644
index 000000000..69b6f30f4
--- /dev/null
+++ b/test/Mono.Linker.Tests/Extensions/NiceIO.cs
@@ -0,0 +1,922 @@
+// The MIT License(MIT)
+// =====================
+//
+// Copyright © `2015-2017` `Lucas Meijer`
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the “Software”), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Mono.Linker.Tests.Extensions
+{
+ public class NPath : IEquatable<NPath>, IComparable
+ {
+ private static readonly StringComparison PathStringComparison = IsLinux() ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
+
+ private readonly string[] _elements;
+ private readonly bool _isRelative;
+ private readonly string _driveLetter;
+
+ #region construction
+
+ public NPath(string path)
+ {
+ if (path == null)
+ throw new ArgumentNullException();
+
+ path = ParseDriveLetter(path, out _driveLetter);
+
+ if (path == "/")
+ {
+ _isRelative = false;
+ _elements = new string[] { };
+ }
+ else
+ {
+ var split = path.Split('/', '\\');
+
+ _isRelative = _driveLetter == null && IsRelativeFromSplitString(split);
+
+ _elements = ParseSplitStringIntoElements(split.Where(s => s.Length > 0).ToArray());
+ }
+ }
+
+ private NPath(string[] elements, bool isRelative, string driveLetter)
+ {
+ _elements = elements;
+ _isRelative = isRelative;
+ _driveLetter = driveLetter;
+ }
+
+ private string[] ParseSplitStringIntoElements(IEnumerable<string> inputs)
+ {
+ var stack = new List<string>();
+
+ foreach (var input in inputs.Where(input => input.Length != 0))
+ {
+ if (input == ".")
+ {
+ if ((stack.Count > 0) && (stack.Last() != "."))
+ continue;
+ }
+ else if (input == "..")
+ {
+ if (HasNonDotDotLastElement(stack))
+ {
+ stack.RemoveAt(stack.Count - 1);
+ continue;
+ }
+ if (!_isRelative)
+ throw new ArgumentException("You cannot create a path that tries to .. past the root");
+ }
+ stack.Add(input);
+ }
+ return stack.ToArray();
+ }
+
+ private static bool HasNonDotDotLastElement(List<string> stack)
+ {
+ return stack.Count > 0 && stack[stack.Count - 1] != "..";
+ }
+
+ private string ParseDriveLetter(string path, out string driveLetter)
+ {
+ if (path.Length >= 2 && path[1] == ':')
+ {
+ driveLetter = path[0].ToString();
+ return path.Substring(2);
+ }
+
+ driveLetter = null;
+ return path;
+ }
+
+ private static bool IsRelativeFromSplitString(string[] split)
+ {
+ if (split.Length < 2)
+ return true;
+
+ return split[0].Length != 0 || !split.Any(s => s.Length > 0);
+ }
+
+ public NPath Combine(params string[] append)
+ {
+ return Combine(append.Select(a => new NPath(a)).ToArray());
+ }
+
+ public NPath Combine(params NPath[] append)
+ {
+ if (!append.All(p => p.IsRelative))
+ throw new ArgumentException("You cannot .Combine a non-relative path");
+
+ return new NPath(ParseSplitStringIntoElements(_elements.Concat(append.SelectMany(p => p._elements))), _isRelative, _driveLetter);
+ }
+
+ public NPath Parent
+ {
+ get
+ {
+ if (_elements.Length == 0)
+ throw new InvalidOperationException("Parent is called on an empty path");
+
+ var newElements = _elements.Take(_elements.Length - 1).ToArray();
+
+ return new NPath(newElements, _isRelative, _driveLetter);
+ }
+ }
+
+ public NPath RelativeTo(NPath path)
+ {
+ if (!IsChildOf(path))
+ {
+ if (!IsRelative && !path.IsRelative && _driveLetter != path._driveLetter)
+ throw new ArgumentException("Path.RelativeTo() was invoked with two paths that are on different volumes. invoked on: " + ToString() + " asked to be made relative to: " + path);
+
+ NPath commonParent = null;
+ foreach (var parent in RecursiveParents)
+ {
+ commonParent = path.RecursiveParents.FirstOrDefault(otherParent => otherParent == parent);
+
+ if (commonParent != null)
+ break;
+ }
+
+ if (commonParent == null)
+ throw new ArgumentException("Path.RelativeTo() was unable to find a common parent between " + ToString() + " and " + path);
+
+ if (IsRelative && path.IsRelative && commonParent.IsEmpty())
+ throw new ArgumentException("Path.RelativeTo() was invoked with two relative paths that do not share a common parent. Invoked on: " + ToString() + " asked to be made relative to: " + path);
+
+ var depthDiff = path.Depth - commonParent.Depth;
+ return new NPath(Enumerable.Repeat("..", depthDiff).Concat(_elements.Skip(commonParent.Depth)).ToArray(), true, null);
+ }
+
+ return new NPath(_elements.Skip(path._elements.Length).ToArray(), true, null);
+ }
+
+ public NPath ChangeExtension(string extension)
+ {
+ ThrowIfRoot();
+
+ var newElements = (string[])_elements.Clone();
+ newElements[newElements.Length - 1] = Path.ChangeExtension(_elements[_elements.Length - 1], WithDot(extension));
+ if (extension == string.Empty)
+ newElements[newElements.Length - 1] = newElements[newElements.Length - 1].TrimEnd('.');
+ return new NPath(newElements, _isRelative, _driveLetter);
+ }
+ #endregion construction
+
+ #region inspection
+
+ public bool IsRelative
+ {
+ get { return _isRelative; }
+ }
+
+ public string FileName
+ {
+ get
+ {
+ ThrowIfRoot();
+
+ return _elements.Last();
+ }
+ }
+
+ public string FileNameWithoutExtension
+ {
+ get { return Path.GetFileNameWithoutExtension(FileName); }
+ }
+
+ public IEnumerable<string> Elements
+ {
+ get { return _elements; }
+ }
+
+ public int Depth
+ {
+ get { return _elements.Length; }
+ }
+
+ public bool Exists(string append = "")
+ {
+ return Exists(new NPath(append));
+ }
+
+ public bool Exists(NPath append)
+ {
+ return FileExists(append) || DirectoryExists(append);
+ }
+
+ public bool DirectoryExists(string append = "")
+ {
+ return DirectoryExists(new NPath(append));
+ }
+
+ public bool DirectoryExists(NPath append)
+ {
+ return Directory.Exists(Combine(append).ToString());
+ }
+
+ public bool FileExists(string append = "")
+ {
+ return FileExists(new NPath(append));
+ }
+
+ public bool FileExists(NPath append)
+ {
+ return File.Exists(Combine(append).ToString());
+ }
+
+ public string ExtensionWithDot
+ {
+ get
+ {
+ if (IsRoot)
+ throw new ArgumentException("A root directory does not have an extension");
+
+ var last = _elements.Last();
+ var index = last.LastIndexOf(".");
+ if (index < 0) return String.Empty;
+ return last.Substring(index);
+ }
+ }
+
+ public string InQuotes()
+ {
+ return "\"" + ToString() + "\"";
+ }
+
+ public string InQuotes(SlashMode slashMode)
+ {
+ return "\"" + ToString(slashMode) + "\"";
+ }
+
+ public override string ToString()
+ {
+ return ToString(SlashMode.Native);
+ }
+
+ public string ToString(SlashMode slashMode)
+ {
+ // Check if it's linux root /
+ if (IsRoot && string.IsNullOrEmpty(_driveLetter))
+ return Slash(slashMode).ToString();
+
+ if (_isRelative && _elements.Length == 0)
+ return ".";
+
+ var sb = new StringBuilder();
+ if (_driveLetter != null)
+ {
+ sb.Append(_driveLetter);
+ sb.Append(":");
+ }
+ if (!_isRelative)
+ sb.Append(Slash(slashMode));
+ var first = true;
+ foreach (var element in _elements)
+ {
+ if (!first)
+ sb.Append(Slash(slashMode));
+
+ sb.Append(element);
+ first = false;
+ }
+ return sb.ToString();
+ }
+
+ public static implicit operator string(NPath path)
+ {
+ return path.ToString();
+ }
+
+ static char Slash(SlashMode slashMode)
+ {
+ switch (slashMode)
+ {
+ case SlashMode.Backward:
+ return '\\';
+ case SlashMode.Forward:
+ return '/';
+ default:
+ return Path.DirectorySeparatorChar;
+ }
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj == null)
+ return false;
+
+ // If parameter cannot be cast to Point return false.
+ var p = obj as NPath;
+ if ((Object)p == null)
+ return false;
+
+ return Equals(p);
+ }
+
+ public bool Equals(NPath p)
+ {
+ if (p._isRelative != _isRelative)
+ return false;
+
+ if (!string.Equals(p._driveLetter, _driveLetter, PathStringComparison))
+ return false;
+
+ if (p._elements.Length != _elements.Length)
+ return false;
+
+ for (var i = 0; i != _elements.Length; i++)
+ if (!string.Equals(p._elements[i], _elements[i], PathStringComparison))
+ return false;
+
+ return true;
+ }
+
+ public static bool operator ==(NPath a, NPath b)
+ {
+ // If both are null, or both are same instance, return true.
+ if (ReferenceEquals(a, b))
+ return true;
+
+ // If one is null, but not both, return false.
+ if (((object)a == null) || ((object)b == null))
+ return false;
+
+ // Return true if the fields match:
+ return a.Equals(b);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hash = 17;
+ // Suitable nullity checks etc, of course :)
+ hash = hash * 23 + _isRelative.GetHashCode();
+ foreach (var element in _elements)
+ hash = hash * 23 + element.GetHashCode();
+ if (_driveLetter != null)
+ hash = hash * 23 + _driveLetter.GetHashCode();
+ return hash;
+ }
+ }
+
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ return -1;
+
+ return this.ToString().CompareTo(((NPath)obj).ToString());
+ }
+
+ public static bool operator !=(NPath a, NPath b)
+ {
+ return !(a == b);
+ }
+
+ public bool HasExtension(params string[] extensions)
+ {
+ var extensionWithDotLower = ExtensionWithDot.ToLower();
+ return extensions.Any(e => WithDot(e).ToLower() == extensionWithDotLower);
+ }
+
+ private static string WithDot(string extension)
+ {
+ return extension.StartsWith(".") ? extension : "." + extension;
+ }
+
+ private bool IsEmpty()
+ {
+ return _elements.Length == 0;
+ }
+
+ public bool IsRoot
+ {
+ get { return _elements.Length == 0 && !_isRelative; }
+ }
+
+ #endregion inspection
+
+ #region directory enumeration
+
+ public IEnumerable<NPath> Files(string filter, bool recurse = false)
+ {
+ return Directory.GetFiles(ToString(), filter, recurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).Select(s => new NPath(s));
+ }
+
+ public IEnumerable<NPath> Files(bool recurse = false)
+ {
+ return Files("*", recurse);
+ }
+
+ public IEnumerable<NPath> Contents(string filter, bool recurse = false)
+ {
+ return Files(filter, recurse).Concat(Directories(filter, recurse));
+ }
+
+ public IEnumerable<NPath> Contents(bool recurse = false)
+ {
+ return Contents("*", recurse);
+ }
+
+ public IEnumerable<NPath> Directories(string filter, bool recurse = false)
+ {
+ return Directory.GetDirectories(ToString(), filter, recurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).Select(s => new NPath(s));
+ }
+
+ public IEnumerable<NPath> Directories(bool recurse = false)
+ {
+ return Directories("*", recurse);
+ }
+
+ #endregion
+
+ #region filesystem writing operations
+ public NPath CreateFile()
+ {
+ ThrowIfRelative();
+ ThrowIfRoot();
+ EnsureParentDirectoryExists();
+ File.WriteAllBytes(ToString(), new byte[0]);
+ return this;
+ }
+
+ public NPath CreateFile(string file)
+ {
+ return CreateFile(new NPath(file));
+ }
+
+ public NPath CreateFile(NPath file)
+ {
+ if (!file.IsRelative)
+ throw new ArgumentException("You cannot call CreateFile() on an existing path with a non relative argument");
+ return Combine(file).CreateFile();
+ }
+
+ public NPath CreateDirectory()
+ {
+ ThrowIfRelative();
+
+ if (IsRoot)
+ throw new NotSupportedException("CreateDirectory is not supported on a root level directory because it would be dangerous:" + ToString());
+
+ Directory.CreateDirectory(ToString());
+ return this;
+ }
+
+ public NPath CreateDirectory(string directory)
+ {
+ return CreateDirectory(new NPath(directory));
+ }
+
+ public NPath CreateDirectory(NPath directory)
+ {
+ if (!directory.IsRelative)
+ throw new ArgumentException("Cannot call CreateDirectory with an absolute argument");
+
+ return Combine(directory).CreateDirectory();
+ }
+
+ public NPath Copy(string dest)
+ {
+ return Copy(new NPath(dest));
+ }
+
+ public NPath Copy(string dest, Func<NPath, bool> fileFilter)
+ {
+ return Copy(new NPath(dest), fileFilter);
+ }
+
+ public NPath Copy(NPath dest)
+ {
+ return Copy(dest, p => true);
+ }
+
+ public NPath Copy(NPath dest, Func<NPath, bool> fileFilter)
+ {
+ ThrowIfRelative();
+ if (dest.IsRelative)
+ dest = Parent.Combine(dest);
+
+ if (dest.DirectoryExists())
+ return CopyWithDeterminedDestination(dest.Combine(FileName), fileFilter);
+
+ return CopyWithDeterminedDestination(dest, fileFilter);
+ }
+
+ public NPath MakeAbsolute()
+ {
+ if (!IsRelative)
+ return this;
+
+ return NPath.CurrentDirectory.Combine(this);
+ }
+
+ NPath CopyWithDeterminedDestination(NPath absoluteDestination, Func<NPath, bool> fileFilter)
+ {
+ if (absoluteDestination.IsRelative)
+ throw new ArgumentException("absoluteDestination must be absolute");
+
+ if (FileExists())
+ {
+ if (!fileFilter(absoluteDestination))
+ return null;
+
+ absoluteDestination.EnsureParentDirectoryExists();
+
+ File.Copy(ToString(), absoluteDestination.ToString(), true);
+ return absoluteDestination;
+ }
+
+ if (DirectoryExists())
+ {
+ absoluteDestination.EnsureDirectoryExists();
+ foreach (var thing in Contents())
+ thing.CopyWithDeterminedDestination(absoluteDestination.Combine(thing.RelativeTo(this)), fileFilter);
+ return absoluteDestination;
+ }
+
+ throw new ArgumentException("Copy() called on path that doesnt exist: " + ToString());
+ }
+
+ public void Delete(DeleteMode deleteMode = DeleteMode.Normal)
+ {
+ ThrowIfRelative();
+
+ if (IsRoot)
+ throw new NotSupportedException("Delete is not supported on a root level directory because it would be dangerous:" + ToString());
+
+ if (FileExists())
+ File.Delete(ToString());
+ else if (DirectoryExists())
+ try
+ {
+ Directory.Delete(ToString(), true);
+ }
+ catch (IOException)
+ {
+ if (deleteMode == DeleteMode.Normal)
+ throw;
+ }
+ else
+ throw new InvalidOperationException("Trying to delete a path that does not exist: " + ToString());
+ }
+
+ public void DeleteIfExists(DeleteMode deleteMode = DeleteMode.Normal)
+ {
+ ThrowIfRelative();
+
+ if (FileExists() || DirectoryExists())
+ Delete(deleteMode);
+ }
+
+ public NPath DeleteContents()
+ {
+ ThrowIfRelative();
+
+ if (IsRoot)
+ throw new NotSupportedException("DeleteContents is not supported on a root level directory because it would be dangerous:" + ToString());
+
+ if (FileExists())
+ throw new InvalidOperationException("It is not valid to perform this operation on a file");
+
+ if (DirectoryExists())
+ {
+ try
+ {
+ Files().Delete();
+ Directories().Delete();
+ }
+ catch (IOException)
+ {
+ if (Files(true).Any())
+ throw;
+ }
+
+ return this;
+ }
+
+ return EnsureDirectoryExists();
+ }
+
+ public static NPath CreateTempDirectory(string myprefix)
+ {
+ var random = new Random();
+ while (true)
+ {
+ var candidate = new NPath(Path.GetTempPath() + "/" + myprefix + "_" + random.Next());
+ if (!candidate.Exists())
+ return candidate.CreateDirectory();
+ }
+ }
+
+ public NPath Move(string dest)
+ {
+ return Move(new NPath(dest));
+ }
+
+ public NPath Move(NPath dest)
+ {
+ ThrowIfRelative();
+
+ if (IsRoot)
+ throw new NotSupportedException("Move is not supported on a root level directory because it would be dangerous:" + ToString());
+
+ if (dest.IsRelative)
+ return Move(Parent.Combine(dest));
+
+ if (dest.DirectoryExists())
+ return Move(dest.Combine(FileName));
+
+ if (FileExists())
+ {
+ dest.EnsureParentDirectoryExists();
+ File.Move(ToString(), dest.ToString());
+ return dest;
+ }
+
+ if (DirectoryExists())
+ {
+ Directory.Move(ToString(), dest.ToString());
+ return dest;
+ }
+
+ throw new ArgumentException("Move() called on a path that doesn't exist: " + ToString());
+ }
+
+ #endregion
+
+ #region special paths
+
+ public static NPath CurrentDirectory
+ {
+ get
+ {
+ return new NPath(Directory.GetCurrentDirectory());
+ }
+ }
+
+ public static NPath HomeDirectory
+ {
+ get
+ {
+ if (Path.DirectorySeparatorChar == '\\')
+ return new NPath(Environment.GetEnvironmentVariable("USERPROFILE"));
+ return new NPath(Environment.GetEnvironmentVariable("HOME"));
+ }
+ }
+
+ public static NPath SystemTemp
+ {
+ get
+ {
+ return new NPath(Path.GetTempPath());
+ }
+ }
+
+ #endregion
+
+ private void ThrowIfRelative()
+ {
+ if (_isRelative)
+ throw new ArgumentException("You are attempting an operation on a Path that requires an absolute path, but the path is relative");
+ }
+
+ private void ThrowIfRoot()
+ {
+ if (IsRoot)
+ throw new ArgumentException("You are attempting an operation that is not valid on a root level directory");
+ }
+
+ public NPath EnsureDirectoryExists(string append = "")
+ {
+ return EnsureDirectoryExists(new NPath(append));
+ }
+
+ public NPath EnsureDirectoryExists(NPath append)
+ {
+ var combined = Combine(append);
+ if (combined.DirectoryExists())
+ return combined;
+ combined.EnsureParentDirectoryExists();
+ combined.CreateDirectory();
+ return combined;
+ }
+
+ public NPath EnsureParentDirectoryExists()
+ {
+ var parent = Parent;
+ parent.EnsureDirectoryExists();
+ return parent;
+ }
+
+ public NPath FileMustExist()
+ {
+ if (!FileExists())
+ throw new FileNotFoundException("File was expected to exist : " + ToString());
+
+ return this;
+ }
+
+ public NPath DirectoryMustExist()
+ {
+ if (!DirectoryExists())
+ throw new DirectoryNotFoundException("Expected directory to exist : " + ToString());
+
+ return this;
+ }
+
+ public bool IsChildOf(string potentialBasePath)
+ {
+ return IsChildOf(new NPath(potentialBasePath));
+ }
+
+ public bool IsChildOf(NPath potentialBasePath)
+ {
+ if ((IsRelative && !potentialBasePath.IsRelative) || !IsRelative && potentialBasePath.IsRelative)
+ throw new ArgumentException("You can only call IsChildOf with two relative paths, or with two absolute paths");
+
+ // If the other path is the root directory, then anything is a child of it as long as it's not a Windows path
+ if (potentialBasePath.IsRoot)
+ {
+ if (_driveLetter != potentialBasePath._driveLetter)
+ return false;
+ return true;
+ }
+
+ if (IsEmpty())
+ return false;
+
+ if (Equals(potentialBasePath))
+ return true;
+
+ return Parent.IsChildOf(potentialBasePath);
+ }
+
+ public IEnumerable<NPath> RecursiveParents
+ {
+ get
+ {
+ var candidate = this;
+ while (true)
+ {
+ if (candidate.IsEmpty())
+ yield break;
+
+ candidate = candidate.Parent;
+ yield return candidate;
+ }
+ }
+ }
+
+ public NPath ParentContaining(string needle)
+ {
+ return ParentContaining(new NPath(needle));
+ }
+
+ public NPath ParentContaining(NPath needle)
+ {
+ ThrowIfRelative();
+
+ return RecursiveParents.FirstOrDefault(p => p.Exists(needle));
+ }
+
+ public NPath WriteAllText(string contents)
+ {
+ ThrowIfRelative();
+ EnsureParentDirectoryExists();
+ File.WriteAllText(ToString(), contents);
+ return this;
+ }
+
+ public string ReadAllText()
+ {
+ ThrowIfRelative();
+ return File.ReadAllText(ToString());
+ }
+
+ public NPath WriteAllLines(string[] contents)
+ {
+ ThrowIfRelative();
+ EnsureParentDirectoryExists();
+ File.WriteAllLines(ToString(), contents);
+ return this;
+ }
+
+ public string[] ReadAllLines()
+ {
+ ThrowIfRelative();
+ return File.ReadAllLines(ToString());
+ }
+
+ public IEnumerable<NPath> CopyFiles(NPath destination, bool recurse, Func<NPath, bool> fileFilter = null)
+ {
+ destination.EnsureDirectoryExists();
+ return Files(recurse).Where(fileFilter ?? AlwaysTrue).Select(file => file.Copy(destination.Combine(file.RelativeTo(this)))).ToArray();
+ }
+
+ public IEnumerable<NPath> MoveFiles(NPath destination, bool recurse, Func<NPath, bool> fileFilter = null)
+ {
+ if (IsRoot)
+ throw new NotSupportedException("MoveFiles is not supported on this directory because it would be dangerous:" + ToString());
+
+ destination.EnsureDirectoryExists();
+ return Files(recurse).Where(fileFilter ?? AlwaysTrue).Select(file => file.Move(destination.Combine(file.RelativeTo(this)))).ToArray();
+ }
+
+ static bool AlwaysTrue(NPath p)
+ {
+ return true;
+ }
+
+ private static bool IsLinux()
+ {
+ return Directory.Exists("/proc");
+ }
+ }
+
+ public static class Extensions
+ {
+ public static IEnumerable<NPath> Copy(this IEnumerable<NPath> self, string dest)
+ {
+ return Copy(self, new NPath(dest));
+ }
+
+ public static IEnumerable<NPath> Copy(this IEnumerable<NPath> self, NPath dest)
+ {
+ if (dest.IsRelative)
+ throw new ArgumentException("When copying multiple files, the destination cannot be a relative path");
+ dest.EnsureDirectoryExists();
+ return self.Select(p => p.Copy(dest.Combine(p.FileName))).ToArray();
+ }
+
+ public static IEnumerable<NPath> Move(this IEnumerable<NPath> self, string dest)
+ {
+ return Move(self, new NPath(dest));
+ }
+
+ public static IEnumerable<NPath> Move(this IEnumerable<NPath> self, NPath dest)
+ {
+ if (dest.IsRelative)
+ throw new ArgumentException("When moving multiple files, the destination cannot be a relative path");
+ dest.EnsureDirectoryExists();
+ return self.Select(p => p.Move(dest.Combine(p.FileName))).ToArray();
+ }
+
+ public static IEnumerable<NPath> Delete(this IEnumerable<NPath> self)
+ {
+ foreach (var p in self)
+ p.Delete();
+ return self;
+ }
+
+ public static IEnumerable<string> InQuotes(this IEnumerable<NPath> self, SlashMode forward = SlashMode.Native)
+ {
+ return self.Select(p => p.InQuotes(forward));
+ }
+
+ public static NPath ToNPath(this string path)
+ {
+ return new NPath(path);
+ }
+ }
+
+ public enum SlashMode
+ {
+ Native,
+ Forward,
+ Backward
+ }
+
+ public enum DeleteMode
+ {
+ Normal,
+ Soft
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj b/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj
new file mode 100644
index 000000000..7da7cae3d
--- /dev/null
+++ b/test/Mono.Linker.Tests/Mono.Linker.Tests.csproj
@@ -0,0 +1,115 @@
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <ProjectGuid>{400A1561-B6B6-482D-9E4C-3DDAEDE5BD07}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AssemblyName>Mono.Linker.Tests</AssemblyName>
+ <StartupObject>
+ </StartupObject>
+ <TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
+ <RootNamespace>Mono.Linker.Tests</RootNamespace>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Core" />
+ <Reference Include="nunit.framework">
+ <HintPath>..\..\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="Properties\" />
+ <Folder Include="TestCasesRunner\" />
+ <Folder Include="Extensions\" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\external\cecil\Mono.Cecil.csproj">
+ <Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
+ <Name>Mono.Cecil</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\external\cecil\symbols\mdb\Mono.Cecil.Mdb.csproj">
+ <Project>{8559dd7f-a16f-46d0-a05a-9139faeba8fd}</Project>
+ <Name>Mono.Cecil.Mdb</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\external\cecil\symbols\pdb\Mono.Cecil.Pdb.csproj">
+ <Project>{63e6915c-7ea4-4d76-ab28-0d7191eea626}</Project>
+ <Name>Mono.Cecil.Pdb</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\src\linker\Mono.Linker.csproj">
+ <Project>{DD28E2B1-057B-4B4D-A04D-B2EBD9E76E46}</Project>
+ <Name>Mono.Linker</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Mono.Linker.Tests.Cases\Mono.Linker.Tests.Cases.csproj">
+ <Project>{B6BEE6AA-ADA0-4E1D-9A17-FBF2936F82B5}</Project>
+ <Name>Mono.Linker.Tests.Cases</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Mono.Linker.Tests.Cases.Expectations\Mono.Linker.Tests.Cases.Expectations.csproj">
+ <Project>{2C26601F-3E2F-45B9-A02F-58EE9296E19E}</Project>
+ <Name>Mono.Linker.Tests.Cases.Expectations</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="TestCasesRunner\CompilerOptions.cs" />
+ <Compile Include="TestCasesRunner\FormattingUtils.cs" />
+ <Compile Include="TestCasesRunner\ILCompiler.cs" />
+ <Compile Include="TestCasesRunner\SourceAndDestinationPair.cs" />
+ <Compile Include="TestCasesRunner\SetupCompileInfo.cs" />
+ <Compile Include="TestCasesRunner\PeVerifier.cs" />
+ <Compile Include="TestCasesRunner\TestCaseAssemblyResolver.cs" />
+ <Compile Include="TestCases\IndividualTests.cs" />
+ <Compile Include="TestCases\TestSuites.cs" />
+ <Compile Include="TestCases\TestDatabase.cs" />
+ <Compile Include="Tests\PreserveActionComparisonTests.cs" />
+ <Compile Include="TestCasesRunner\LinkXmlHelpers.cs" />
+ <Compile Include="TestCasesRunner\LinkedTestCaseResult.cs" />
+ <Compile Include="TestCasesRunner\ManagedCompilationResult.cs" />
+ <Compile Include="TestCasesRunner\TestCaseCollector.cs" />
+ <Compile Include="TestCasesRunner\TestCaseLinkerOptions.cs" />
+ <Compile Include="TestCasesRunner\TestRunner.cs" />
+ <Compile Include="TestCases\TestCase.cs" />
+ <Compile Include="Extensions\NiceIO.cs" />
+ <Compile Include="Extensions\CecilExtensions.cs" />
+ <Compile Include="TestCasesRunner\ExpectationsProvider.cs" />
+ <Compile Include="TestCasesRunner\AssemblyChecker.cs" />
+ <Compile Include="TestCasesRunner\LinkerArgumentBuilder.cs" />
+ <Compile Include="TestCasesRunner\LinkerDriver.cs" />
+ <Compile Include="TestCasesRunner\ObjectFactory.cs" />
+ <Compile Include="TestCasesRunner\ResultChecker.cs" />
+ <Compile Include="TestCasesRunner\TestCaseCompiler.cs" />
+ <Compile Include="TestCasesRunner\TestCaseMetadaProvider.cs" />
+ <Compile Include="TestCasesRunner\TestCaseSandbox.cs" />
+ <Compile Include="Tests\TypeNameParserTests.cs" />
+ <Compile Include="Tests\ParseResponseFileLinesTests.cs" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCases/IndividualTests.cs b/test/Mono.Linker.Tests/TestCases/IndividualTests.cs
new file mode 100644
index 000000000..c8c1a8833
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCases/IndividualTests.cs
@@ -0,0 +1,92 @@
+using System;
+using System.IO;
+using System.Xml;
+using Mono.Linker.Tests.Cases.References.Individual;
+using Mono.Linker.Tests.Cases.Tracing.Individual;
+using Mono.Linker.Tests.TestCases;
+using Mono.Linker.Tests.TestCasesRunner;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCases
+{
+ [TestFixture]
+ public class IndividualTests
+ {
+ [Test]
+ public void CanSkipUnresolved ()
+ {
+ var testcase = CreateIndividualCase (typeof (CanSkipUnresolved));
+ var result = Run (testcase);
+
+ // We can't use the ResultChecker on the output because there will be unresolved types/methods
+ // Let's just make sure that the output assembly exists. That's enough to verify that the linker didn't throw due to the
+ // missing types/methods
+ if (!result.OutputAssemblyPath.Exists ())
+ Assert.Fail ($"The linked assembly is missing. Should have existed at {result.OutputAssemblyPath}");
+ }
+
+ [Test]
+ public void CanEnableDependenciesDump ()
+ {
+ var testcase = CreateIndividualCase (typeof (CanEnableDependenciesDump));
+ var result = Run (testcase);
+
+ var outputPath = result.OutputAssemblyPath.Parent.Combine (Tracer.DefaultDependenciesFileName);
+ if (!outputPath.Exists ())
+ Assert.Fail ($"The dependency dump file is missing. Expected it to exist at {outputPath}");
+ }
+
+ [Test]
+ public void CanDumpDependenciesToUncompressedXml ()
+ {
+ var testcase = CreateIndividualCase (typeof (CanDumpDependenciesToUncompressedXml));
+ var result = Run (testcase);
+
+ var outputPath = result.OutputAssemblyPath.Parent.Combine ("linker-dependencies.xml");
+ if (!outputPath.Exists ())
+ Assert.Fail($"The dependency dump file is missing. Expected it to exist at {outputPath}");
+
+ // Do a basic check to verify that the contents of the file are uncompressed xml
+ using (var reader = new XmlTextReader (outputPath.ToString ())) {
+ reader.Read ();
+ reader.Read ();
+ reader.Read ();
+ Assert.That (reader.Name, Is.EqualTo ("dependencies"), $"Expected to be at the dependencies element, but the current node name is `{reader.Name}`");
+ }
+ }
+
+ [Test]
+ public void CanEnableReducedTracing ()
+ {
+ var testcase = CreateIndividualCase (typeof (CanEnableReducedTracing));
+ var result = Run (testcase);
+
+ // Note: This name needs to match what is setup in the test case arguments to the linker
+ const string expectedDependenciesFileName = "linker-dependencies.xml";
+ var outputPath = result.OutputAssemblyPath.Parent.Combine (expectedDependenciesFileName);
+ if (!outputPath.Exists ())
+ Assert.Fail($"The dependency dump file is missing. Expected it to exist at {outputPath}");
+
+ // Let's go a little bit further and make sure it looks like reducing tracking actually worked.
+ // This is intentionally a loose assertion. This test isn't meant to verify how reduced tracing works,
+ // it's here to make sure that enabling the option enables the behavior.
+ var lineCount = outputPath.ReadAllLines ().Length;
+
+ // When reduced tracing is not enabled there are around 16k of lines in the output file.
+ // With reduced tracing there should be less than 65, but to be safe, we'll check for less than 100.
+ const int expectedMaxLines = 100;
+ Assert.That (lineCount, Is.LessThan (expectedMaxLines), $"There were `{lineCount}` lines in the dump file. This is more than expected max of {expectedMaxLines} and likely indicates reduced tracing was not enabled. Dump file can be found at: {outputPath}");
+ }
+
+ private TestCase CreateIndividualCase (Type testCaseType)
+ {
+ return TestDatabase.CreateCollector ().CreateIndividualCase (testCaseType);
+ }
+
+ protected virtual LinkedTestCaseResult Run (TestCase testCase)
+ {
+ var runner = new TestRunner (new ObjectFactory ());
+ return runner.Run (testCase);
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCases/TestCase.cs b/test/Mono.Linker.Tests/TestCases/TestCase.cs
new file mode 100644
index 000000000..790e41102
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCases/TestCase.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Linq;
+using Mono.Linker.Tests.Extensions;
+
+namespace Mono.Linker.Tests.TestCases {
+ public class TestCase {
+ public TestCase (NPath sourceFile, NPath rootCasesDirectory, NPath originalTestCaseAssemblyPath)
+ {
+ SourceFile = sourceFile;
+ OriginalTestCaseAssemblyPath = originalTestCaseAssemblyPath;
+ Name = sourceFile.FileNameWithoutExtension;
+ DisplayName = $"{sourceFile.RelativeTo (rootCasesDirectory).Parent.ToString (SlashMode.Forward).Replace ('/', '.')}.{sourceFile.FileNameWithoutExtension}";
+
+ // A little hacky, but good enough for name. No reason why namespace & type names
+ // should not follow the directory structure
+ ReconstructedFullTypeName = $"{sourceFile.Parent.RelativeTo (rootCasesDirectory.Parent).ToString (SlashMode.Forward).Replace ('/', '.')}.{sourceFile.FileNameWithoutExtension}";
+
+ var firstParentRelativeToRoot = SourceFile.RelativeTo (rootCasesDirectory).Elements.First ();
+ TestSuiteDirectory = rootCasesDirectory.Combine (firstParentRelativeToRoot);
+ }
+
+ public string Name { get; }
+
+ public string DisplayName { get; }
+
+ public NPath SourceFile { get; }
+
+ public NPath OriginalTestCaseAssemblyPath { get; }
+
+ public string ReconstructedFullTypeName { get; }
+
+ public bool HasLinkXmlFile {
+ get { return SourceFile.ChangeExtension ("xml").FileExists (); }
+ }
+
+ public NPath LinkXmlFile {
+ get
+ {
+ if (!HasLinkXmlFile)
+ throw new InvalidOperationException ("This test case does not have a link xml file");
+
+ return SourceFile.ChangeExtension ("xml");
+ }
+ }
+
+ public NPath TestSuiteDirectory { get; }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCases/TestDatabase.cs b/test/Mono.Linker.Tests/TestCases/TestDatabase.cs
new file mode 100644
index 000000000..62a1a0009
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCases/TestDatabase.cs
@@ -0,0 +1,175 @@
+using System.Linq;
+using System.Collections.Generic;
+using NUnit.Framework;
+using System.Runtime.CompilerServices;
+using System.IO;
+using Mono.Linker.Tests.TestCasesRunner;
+
+namespace Mono.Linker.Tests.TestCases
+{
+ public static class TestDatabase
+ {
+ private static TestCase[] _cachedAllCases;
+
+ public static IEnumerable<TestCaseData> XmlTests()
+ {
+ return NUnitCasesBySuiteName("LinkXml");
+ }
+
+ public static IEnumerable<TestCaseData> BasicTests()
+ {
+ return NUnitCasesBySuiteName("Basic");
+ }
+
+ public static IEnumerable<TestCaseData> AttributeTests()
+ {
+ return NUnitCasesBySuiteName("Attributes");
+ }
+
+ public static IEnumerable<TestCaseData> AttributeDebuggerTests ()
+ {
+ return NUnitCasesBySuiteName ("Attributes.Debugger");
+ }
+
+ public static IEnumerable<TestCaseData> GenericsTests()
+ {
+ return NUnitCasesBySuiteName("Generics");
+ }
+
+ public static IEnumerable<TestCaseData> CoreLinkTests()
+ {
+ return NUnitCasesBySuiteName("CoreLink");
+ }
+
+ public static IEnumerable<TestCaseData> StaticsTests()
+ {
+ return NUnitCasesBySuiteName("Statics");
+ }
+
+ public static IEnumerable<TestCaseData> InteropTests()
+ {
+ return NUnitCasesBySuiteName("Interop");
+ }
+
+ public static IEnumerable<TestCaseData> ReferencesTests()
+ {
+ return NUnitCasesBySuiteName("References");
+ }
+
+ public static IEnumerable<TestCaseData> ResourcesTests ()
+ {
+ return NUnitCasesBySuiteName ("Resources");
+ }
+
+ public static IEnumerable<TestCaseData> TypeForwardingTests ()
+ {
+ return NUnitCasesBySuiteName ("TypeForwarding");
+ }
+
+ public static IEnumerable<TestCaseData> TestFrameworkTests ()
+ {
+ return NUnitCasesBySuiteName ("TestFramework");
+ }
+
+ public static IEnumerable<TestCaseData> ReflectionTests ()
+ {
+ return NUnitCasesBySuiteName ("Reflection");
+ }
+
+ public static IEnumerable<TestCaseData> SymbolsTests ()
+ {
+ return NUnitCasesBySuiteName ("Symbols");
+ }
+
+ public static IEnumerable<TestCaseData> PreserveDependenciesTests ()
+ {
+ return NUnitCasesBySuiteName ("PreserveDependencies");
+ }
+
+ public static IEnumerable<TestCaseData> LibrariesTests ()
+ {
+ return NUnitCasesBySuiteName ("Libraries");
+ }
+
+ public static IEnumerable<TestCaseData> AdvancedTests ()
+ {
+ return NUnitCasesBySuiteName ("Advanced");
+ }
+
+ public static IEnumerable<TestCaseData> InheritanceInterfaceTests ()
+ {
+ return NUnitCasesBySuiteName ("Inheritance.Interfaces");
+ }
+
+ public static IEnumerable<TestCaseData> InheritanceAbstractClassTests ()
+ {
+ return NUnitCasesBySuiteName ("Inheritance.AbstractClasses");
+ }
+
+ public static IEnumerable<TestCaseData> InheritanceVirtualMethodsTests ()
+ {
+ return NUnitCasesBySuiteName ("Inheritance.VirtualMethods");
+ }
+
+ public static IEnumerable<TestCaseData> InheritanceComplexTests ()
+ {
+ return NUnitCasesBySuiteName ("Inheritance.Complex");
+ }
+
+ public static IEnumerable<TestCaseData> BCLFeaturesTests ()
+ {
+ return NUnitCasesBySuiteName ("BCLFeatures");
+ }
+
+ public static IEnumerable<TestCaseData> CommandLineTests ()
+ {
+ return NUnitCasesBySuiteName ("CommandLine");
+ }
+
+ public static TestCaseCollector CreateCollector ()
+ {
+ string rootSourceDirectory;
+ string testCaseAssemblyPath;
+ GetDirectoryPaths (out rootSourceDirectory, out testCaseAssemblyPath);
+ return new TestCaseCollector (rootSourceDirectory, testCaseAssemblyPath);
+ }
+
+ static IEnumerable<TestCase> AllCases ()
+ {
+ if (_cachedAllCases == null)
+ _cachedAllCases = CreateCollector ()
+ .Collect ()
+ .OrderBy (c => c.DisplayName)
+ .ToArray ();
+
+ return _cachedAllCases;
+ }
+
+ static IEnumerable<TestCaseData> NUnitCasesBySuiteName(string suiteName)
+ {
+ return AllCases()
+ .Where(c => c.TestSuiteDirectory.FileName == suiteName)
+ .Select(c => CreateNUnitTestCase(c, c.DisplayName.Substring(suiteName.Length + 1)))
+ .OrderBy(c => c.TestName);
+ }
+
+ static TestCaseData CreateNUnitTestCase(TestCase testCase, string displayName)
+ {
+ var data = new TestCaseData(testCase);
+ data.SetName(displayName);
+ return data;
+ }
+
+ static void GetDirectoryPaths(out string rootSourceDirectory, out string testCaseAssemblyPath, [CallerFilePath] string thisFile = null)
+ {
+ var thisDirectory = Path.GetDirectoryName(thisFile);
+ rootSourceDirectory = Path.GetFullPath(Path.Combine(thisDirectory, "..", "..", "Mono.Linker.Tests.Cases"));
+#if DEBUG
+ var configDirectoryName = "Debug";
+#else
+ var configDirectoryName = "Release";
+#endif
+ testCaseAssemblyPath = Path.GetFullPath(Path.Combine(rootSourceDirectory, "bin", configDirectoryName, "Mono.Linker.Tests.Cases.dll"));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCases/TestSuites.cs b/test/Mono.Linker.Tests/TestCases/TestSuites.cs
new file mode 100644
index 000000000..994448f68
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCases/TestSuites.cs
@@ -0,0 +1,154 @@
+using Mono.Linker.Tests.TestCasesRunner;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCases
+{
+ [TestFixture]
+ public class All
+ {
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.BasicTests))]
+ public void BasicTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.AdvancedTests))]
+ public void AdvancedTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.XmlTests))]
+ public void XmlTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.AttributeTests))]
+ public void AttributesTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.AttributeDebuggerTests))]
+ public void AttributesDebuggerTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.GenericsTests))]
+ public void GenericsTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.StaticsTests))]
+ public void StaticsTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.CoreLinkTests))]
+ public void CoreLinkTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.InteropTests))]
+ public void InteropTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource(typeof(TestDatabase), nameof(TestDatabase.ReferencesTests))]
+ public void ReferencesTests(TestCase testCase)
+ {
+ Run(testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.ResourcesTests))]
+ public void ResourcesTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.TypeForwardingTests))]
+ public void TypeForwardingTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource(typeof (TestDatabase), nameof (TestDatabase.TestFrameworkTests))]
+ public void TestFrameworkTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.ReflectionTests))]
+ public void ReflectionTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.PreserveDependenciesTests))]
+ public void PreserveDependenciesTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.SymbolsTests))]
+ public void SymbolsTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.LibrariesTests))]
+ public void LibrariesTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.InheritanceInterfaceTests))]
+ public void InheritanceInterfaceTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.InheritanceAbstractClassTests))]
+ public void InheritanceAbstractClassTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.InheritanceVirtualMethodsTests))]
+ public void InheritanceVirtualMethodsTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.InheritanceComplexTests))]
+ public void InheritanceComplexTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.BCLFeaturesTests))]
+ public void BCLFeaturesTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ [TestCaseSource (typeof (TestDatabase), nameof (TestDatabase.CommandLineTests))]
+ public void CommandLineTests (TestCase testCase)
+ {
+ Run (testCase);
+ }
+
+ protected virtual void Run (TestCase testCase)
+ {
+ var runner = new TestRunner (new ObjectFactory ());
+ var linkedResult = runner.Run (testCase);
+ new ResultChecker ().Check (linkedResult);
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs b/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs
new file mode 100644
index 000000000..9893a82a1
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs
@@ -0,0 +1,746 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Extensions;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class AssemblyChecker {
+ readonly AssemblyDefinition originalAssembly, linkedAssembly;
+
+ HashSet<string> linkedMembers;
+ HashSet<string> verifiedGeneratedFields = new HashSet<string> ();
+ HashSet<string> verifiedEventMethods = new HashSet<string>();
+ HashSet<string> verifiedGeneratedTypes = new HashSet<string> ();
+
+ public AssemblyChecker (AssemblyDefinition original, AssemblyDefinition linked)
+ {
+ this.originalAssembly = original;
+ this.linkedAssembly = linked;
+ }
+
+ public void Verify ()
+ {
+ // TODO: Implement fully, probably via custom Kept attribute
+ Assert.IsFalse (linkedAssembly.MainModule.HasExportedTypes);
+
+ VerifyCustomAttributes (originalAssembly, linkedAssembly);
+ VerifySecurityAttributes (originalAssembly, linkedAssembly);
+
+ foreach (var originalModule in originalAssembly.Modules)
+ VerifyModule (originalModule, linkedAssembly.Modules.FirstOrDefault (m => m.Name == originalModule.Name));
+
+ VerifyResources (originalAssembly, linkedAssembly);
+ VerifyReferences (originalAssembly, linkedAssembly);
+
+ linkedMembers = new HashSet<string> (linkedAssembly.MainModule.AllMembers ().Select (s => {
+ return s.FullName;
+ }), StringComparer.Ordinal);
+
+ var membersToAssert = originalAssembly.MainModule.Types;
+ foreach (var originalMember in membersToAssert) {
+ var td = originalMember as TypeDefinition;
+ if (td != null) {
+ if (td.Name == "<Module>") {
+ linkedMembers.Remove (td.Name);
+ continue;
+ }
+
+ TypeDefinition linkedType = linkedAssembly.MainModule.GetType (originalMember.FullName);
+ VerifyTypeDefinition (td, linkedType);
+ linkedMembers.Remove (td.FullName);
+
+ continue;
+ }
+
+ throw new NotImplementedException ($"Don't know how to check member of type {originalMember.GetType ()}");
+ }
+
+ Assert.IsEmpty (linkedMembers, "Linked output includes unexpected member");
+ }
+
+ protected virtual void VerifyModule (ModuleDefinition original, ModuleDefinition linked)
+ {
+ // We never link away a module today so let's make sure the linked one isn't null
+ if (linked == null)
+ Assert.Fail ($"Linked assembly `{original.Assembly.Name.Name}` is missing module `{original.Name}`");
+
+ VerifyCustomAttributes (original, linked);
+ }
+
+ protected virtual void VerifyTypeDefinition (TypeDefinition original, TypeDefinition linked)
+ {
+ if (linked != null && verifiedGeneratedTypes.Contains (linked.FullName))
+ return;
+
+ ModuleDefinition linkedModule = linked?.Module;
+
+ //
+ // Little bit complex check to allow easier test writting to match
+ // - It has [Kept] attribute or any variation of it
+ // - It contains Main method
+ // - It contains at least one member which has [Kept] attribute (not recursive)
+ //
+ bool expectedKept =
+ original.HasAttributeDerivedFrom (nameof (KeptAttribute)) ||
+ (linked != null && linkedModule.Assembly.EntryPoint?.DeclaringType == linked) ||
+ original.AllMembers ().Any (l => l.HasAttribute (nameof (KeptAttribute)));
+
+ if (!expectedKept) {
+ if (linked != null)
+ Assert.Fail ($"Type `{original}' should have been removed");
+
+ return;
+ }
+
+ VerifyTypeDefinitionKept (original, linked);
+ }
+
+ protected virtual void VerifyTypeDefinitionKept (TypeDefinition original, TypeDefinition linked)
+ {
+ if (linked == null)
+ Assert.Fail ($"Type `{original}' should have been kept");
+
+ if (!original.IsInterface)
+ VerifyBaseType (original, linked);
+
+ VerifyInterfaces (original, linked);
+ VerifyPseudoAttributes (original, linked);
+ VerifyGenericParameters (original, linked);
+ VerifyCustomAttributes (original, linked);
+ VerifySecurityAttributes (original, linked);
+
+ VerifyFixedBufferFields (original, linked);
+
+ foreach (var td in original.NestedTypes) {
+ VerifyTypeDefinition (td, linked?.NestedTypes.FirstOrDefault (l => td.FullName == l.FullName));
+ linkedMembers.Remove (td.FullName);
+ }
+
+ // Need to check properties before fields so that the KeptBackingFieldAttribute is handled correctly
+ foreach (var p in original.Properties) {
+ VerifyProperty (p, linked?.Properties.FirstOrDefault (l => p.Name == l.Name), linked);
+ linkedMembers.Remove (p.FullName);
+ }
+ // Need to check events before fields so that the KeptBackingFieldAttribute is handled correctly
+ foreach (var e in original.Events) {
+ VerifyEvent (e, linked?.Events.FirstOrDefault (l => e.Name == l.Name), linked);
+ linkedMembers.Remove (e.FullName);
+ }
+
+ // Need to check delegate cache fields before the normal field check
+ VerifyDelegateBackingFields (original, linked);
+
+ foreach (var f in original.Fields) {
+ if (verifiedGeneratedFields.Contains (f.FullName))
+ continue;
+ VerifyField (f, linked?.Fields.FirstOrDefault (l => f.Name == l.Name));
+ linkedMembers.Remove (f.FullName);
+ }
+
+ foreach (var m in original.Methods) {
+ if (verifiedEventMethods.Contains (m.FullName))
+ continue;
+ VerifyMethod (m, linked?.Methods.FirstOrDefault (l => m.GetSignature () == l.GetSignature ()));
+ linkedMembers.Remove (m.FullName);
+ }
+ }
+
+ void VerifyBaseType (TypeDefinition src, TypeDefinition linked)
+ {
+ string expectedBaseName;
+ var expectedBaseGenericAttr = src.CustomAttributes.FirstOrDefault (w => w.AttributeType.Name == nameof (KeptBaseTypeAttribute) && w.ConstructorArguments.Count > 1);
+ if (expectedBaseGenericAttr != null) {
+ StringBuilder builder = new StringBuilder ();
+ builder.Append (expectedBaseGenericAttr.ConstructorArguments [0].Value);
+ builder.Append ("<");
+ bool separator = false;
+ foreach (var caa in (CustomAttributeArgument[])expectedBaseGenericAttr.ConstructorArguments [1].Value) {
+ if (separator)
+ builder.Append (",");
+ else
+ separator = true;
+
+ var arg = (CustomAttributeArgument)caa.Value;
+ builder.Append (arg.Value);
+ }
+
+ builder.Append (">");
+ expectedBaseName = builder.ToString ();
+ } else {
+ var defaultBaseType = src.IsEnum ? "System.Enum" : src.IsValueType ? "System.ValueType" : "System.Object";
+ expectedBaseName = GetCustomAttributeCtorValues<object> (src, nameof (KeptBaseTypeAttribute)).FirstOrDefault ()?.ToString () ?? defaultBaseType;
+ }
+ Assert.AreEqual (expectedBaseName, linked.BaseType?.FullName, $"Incorrect base type on : {linked.Name}");
+ }
+
+ void VerifyInterfaces (TypeDefinition src, TypeDefinition linked)
+ {
+ var expectedInterfaces = new HashSet<string> (GetCustomAttributeCtorValues<object> (src, nameof (KeptInterfaceAttribute)).Select (val => val.ToString ()));
+ if (expectedInterfaces.Count == 0) {
+ Assert.IsFalse (linked.HasInterfaces, $"Type `{src}' has unexpected interfaces");
+ } else {
+ foreach (var iface in linked.Interfaces) {
+ Assert.IsTrue (expectedInterfaces.Remove (iface.InterfaceType.FullName), $"Type `{src}' interface `{iface.InterfaceType.FullName}' should have been removed");
+ }
+
+ Assert.IsEmpty (expectedInterfaces, $"Unexpected interfaces on {src}");
+ }
+ }
+
+ void VerifyField (FieldDefinition src, FieldDefinition linked)
+ {
+ bool expectedKept = ShouldBeKept (src);
+
+ if (!expectedKept) {
+ if (linked != null)
+ Assert.Fail ($"Field `{src}' should have been removed");
+
+ return;
+ }
+
+ VerifyFieldKept (src, linked);
+ }
+
+ void VerifyFieldKept (FieldDefinition src, FieldDefinition linked)
+ {
+ if (linked == null)
+ Assert.Fail ($"Field `{src}' should have been kept");
+
+ Assert.AreEqual (src?.Constant, linked?.Constant, $"Field `{src}' value");
+
+ VerifyPseudoAttributes (src, linked);
+ VerifyCustomAttributes (src, linked);
+ }
+
+ void VerifyProperty (PropertyDefinition src, PropertyDefinition linked, TypeDefinition linkedType)
+ {
+ VerifyMemberBackingField (src, linkedType);
+
+ bool expectedKept = ShouldBeKept (src);
+
+ if (!expectedKept) {
+ if (linked != null)
+ Assert.Fail ($"Property `{src}' should have been removed");
+
+ return;
+ }
+
+ if (linked == null)
+ Assert.Fail ($"Property `{src}' should have been kept");
+
+ Assert.AreEqual (src?.Constant, linked?.Constant, $"Property `{src}' value");
+
+ VerifyPseudoAttributes (src, linked);
+ VerifyCustomAttributes (src, linked);
+ }
+
+ void VerifyEvent (EventDefinition src, EventDefinition linked, TypeDefinition linkedType)
+ {
+ VerifyMemberBackingField (src, linkedType);
+
+ bool expectedKept = ShouldBeKept (src);
+
+ if (!expectedKept) {
+ if (linked != null)
+ Assert.Fail ($"Event `{src}' should have been removed");
+
+ return;
+ }
+
+ if (linked == null)
+ Assert.Fail ($"Event `{src}' should have been kept");
+
+ if (src.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (KeptEventAddMethodAttribute))) {
+ VerifyMethodInternal (src.AddMethod, linked.AddMethod, true);
+ verifiedEventMethods.Add (src.AddMethod.FullName);
+ linkedMembers.Remove (src.AddMethod.FullName);
+ }
+
+ if (src.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (KeptEventRemoveMethodAttribute))) {
+ VerifyMethodInternal (src.RemoveMethod, linked.RemoveMethod, true);
+ verifiedEventMethods.Add (src.RemoveMethod.FullName);
+ linkedMembers.Remove (src.RemoveMethod.FullName);
+ }
+
+ VerifyPseudoAttributes (src, linked);
+ VerifyCustomAttributes (src, linked);
+ }
+
+ void VerifyMethod (MethodDefinition src, MethodDefinition linked)
+ {
+ bool expectedKept = ShouldMethodBeKept (src);
+ VerifyMethodInternal (src, linked, expectedKept);
+ }
+
+
+ void VerifyMethodInternal (MethodDefinition src, MethodDefinition linked, bool expectedKept)
+ {
+ if (!expectedKept) {
+ if (linked != null)
+ Assert.Fail ($"Method `{src.FullName}' should have been removed");
+
+ return;
+ }
+
+ VerifyMethodKept (src, linked);
+ }
+
+ void VerifyMemberBackingField (IMemberDefinition src, TypeDefinition linkedType)
+ {
+ var keptBackingFieldAttribute = src.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == nameof (KeptBackingFieldAttribute));
+ if (keptBackingFieldAttribute == null)
+ return;
+
+ var backingFieldName = src.MetadataToken.TokenType == TokenType.Property
+ ? $"<{src.Name}>k__BackingField" : src.Name;
+ var srcField = src.DeclaringType.Fields.FirstOrDefault (f => f.Name == backingFieldName);
+
+ if (srcField == null) {
+ // Can add more here if necessary
+ backingFieldName = backingFieldName.Replace ("System.Int32", "int");
+ backingFieldName = backingFieldName.Replace ("System.String", "string");
+ backingFieldName = backingFieldName.Replace ("System.Char", "char");
+
+ srcField = src.DeclaringType.Fields.FirstOrDefault (f => f.Name == backingFieldName);
+ }
+
+ if (srcField == null)
+ Assert.Fail ($"{src.MetadataToken.TokenType} `{src}', could not locate the expected backing field {backingFieldName}");
+
+ VerifyFieldKept (srcField, linkedType?.Fields.FirstOrDefault (l => srcField.Name == l.Name));
+ verifiedGeneratedFields.Add (srcField.FullName);
+ linkedMembers.Remove (srcField.FullName);
+ }
+
+ protected virtual void VerifyMethodKept (MethodDefinition src, MethodDefinition linked)
+ {
+ if (linked == null)
+ Assert.Fail ($"Method `{src.FullName}' should have been kept");
+
+ VerifyPseudoAttributes (src, linked);
+ VerifyGenericParameters (src, linked);
+ VerifyCustomAttributes (src, linked);
+ VerifyParameters (src, linked);
+ VerifySecurityAttributes (src, linked);
+ VerifyArrayInitializers (src, linked);
+ VerifyMethodBody (src, linked);
+ }
+
+ protected virtual void VerifyMethodBody (MethodDefinition src, MethodDefinition linked)
+ {
+ if (!src.HasBody)
+ return;
+
+ VerifyExceptionHandlers (src, linked);
+ VerifyInstructions (src, linked);
+ VerifyLocals (src, linked);
+ }
+
+ protected static void VerifyInstructions (MethodDefinition src, MethodDefinition linked)
+ {
+ VerifyBodyProperties (
+ src,
+ linked,
+ nameof (ExpectedInstructionSequenceAttribute),
+ nameof (ExpectBodyModifiedAttribute),
+ "instructions",
+ m => m.Body.Instructions.Select (ins => ins.OpCode.ToString ().ToLower()).ToArray (),
+ attr => GetStringArrayAttributeValue (attr).Select (v => v.ToLower ()).ToArray ());
+ }
+
+ static void VerifyExceptionHandlers (MethodDefinition src, MethodDefinition linked)
+ {
+ VerifyBodyProperties (
+ src,
+ linked,
+ nameof (ExpectedExceptionHandlerSequenceAttribute),
+ nameof (ExpectExceptionHandlersModifiedAttribute),
+ "exception handlers",
+ m => m.Body.ExceptionHandlers.Select (h => h.HandlerType.ToString ().ToLower ()).ToArray (),
+ attr => GetStringArrayAttributeValue (attr).Select (v => v.ToLower ()).ToArray ());
+ }
+
+ static void VerifyLocals (MethodDefinition src, MethodDefinition linked)
+ {
+ VerifyBodyProperties (
+ src,
+ linked,
+ nameof (ExpectedLocalsSequenceAttribute),
+ nameof (ExpectLocalsModifiedAttribute),
+ "locals",
+ m => m.Body.Variables.Select (v => v.VariableType.ToString ()).ToArray (),
+ attr => GetStringOrTypeArrayAttributeValue (attr).ToArray ());
+ }
+
+ protected static void VerifyBodyProperties (MethodDefinition src, MethodDefinition linked, string sequenceAttributeName, string expectModifiedAttributeName,
+ string propertyDescription,
+ Func<MethodDefinition, string []> valueCollector,
+ Func<CustomAttribute, string []> getExpectFromSequenceAttribute)
+ {
+ var expectedSequenceAttribute = src.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == sequenceAttributeName);
+ var linkedValues = valueCollector (linked);
+ var srcValues = valueCollector (src);
+
+ if (src.CustomAttributes.Any (attr => attr.AttributeType.Name == expectModifiedAttributeName)) {
+ Assert.That (
+ linkedValues,
+ Is.Not.EquivalentTo (srcValues),
+ $"Expected method `{src} to have {propertyDescription} modified, however, the {propertyDescription} were the same as the original\n{FormattingUtils.FormatSequenceCompareFailureMessage (linkedValues, srcValues)}");
+ } else if (expectedSequenceAttribute != null) {
+ var expected = getExpectFromSequenceAttribute(expectedSequenceAttribute).ToArray();
+ Assert.That(
+ linkedValues,
+ Is.EquivalentTo (expected),
+ $"Expected method `{src} to have it's {propertyDescription} modified, however, the sequence of {propertyDescription} does not match the expected value\n{FormattingUtils.FormatSequenceCompareFailureMessage2 (linkedValues, expected, srcValues)}");
+ } else {
+ Assert.That(
+ linkedValues,
+ Is.EquivalentTo (srcValues),
+ $"Expected method `{src} to have it's {propertyDescription} unchanged, however, the {propertyDescription} differ from the original\n{FormattingUtils.FormatSequenceCompareFailureMessage (linkedValues, srcValues)}");
+ }
+ }
+
+ void VerifyReferences (AssemblyDefinition original, AssemblyDefinition linked)
+ {
+ var expected = original.MainModule.AllDefinedTypes ()
+ .SelectMany (t => GetCustomAttributeCtorValues<string> (t, nameof (KeptReferenceAttribute)))
+ .Select (ReduceAssemblyFileNameOrNameToNameOnly)
+ .ToArray ();
+
+ /*
+ - The test case will always need to have at least 1 reference.
+ - Forcing all tests to define their expected references seems tedious
+
+ Given the above, let's assume that when no [KeptReference] attributes are present,
+ the test case does not want to make any assertions regarding references.
+
+ Once 1 kept reference attribute is used, the test will need to define all of of it's expected references
+ */
+ if (expected.Length == 0)
+ return;
+
+ var actual = linked.MainModule.AssemblyReferences
+ .Select (name => name.Name)
+ .ToArray ();
+
+ Assert.That (actual, Is.EquivalentTo (expected));
+ }
+
+ string ReduceAssemblyFileNameOrNameToNameOnly (string fileNameOrAssemblyName)
+ {
+ if (fileNameOrAssemblyName.EndsWith (".dll") || fileNameOrAssemblyName.EndsWith (".exe") || fileNameOrAssemblyName.EndsWith (".winmd"))
+ return System.IO.Path.GetFileNameWithoutExtension (fileNameOrAssemblyName);
+
+ // It must already be just the assembly name
+ return fileNameOrAssemblyName;
+ }
+
+ void VerifyResources (AssemblyDefinition original, AssemblyDefinition linked)
+ {
+ var expectedResources = original.MainModule.AllDefinedTypes ()
+ .SelectMany (t => GetCustomAttributeCtorValues<string> (t, nameof (KeptResourceAttribute)));
+
+ Assert.That (linked.MainModule.Resources.Select (r => r.Name), Is.EquivalentTo (expectedResources));
+ }
+
+ protected virtual void VerifyPseudoAttributes (MethodDefinition src, MethodDefinition linked)
+ {
+ var expected = (MethodAttributes) GetExpectedPseudoAttributeValue(src, (uint) src.Attributes);
+ Assert.AreEqual (expected, linked.Attributes, $"Method `{src}' pseudo attributes did not match expected");
+ }
+
+ protected virtual void VerifyPseudoAttributes (TypeDefinition src, TypeDefinition linked)
+ {
+ var expected = (TypeAttributes) GetExpectedPseudoAttributeValue(src, (uint) src.Attributes);
+ Assert.AreEqual (expected, linked.Attributes, $"Type `{src}' pseudo attributes did not match expected");
+ }
+
+ protected virtual void VerifyPseudoAttributes (FieldDefinition src, FieldDefinition linked)
+ {
+ var expected = (FieldAttributes) GetExpectedPseudoAttributeValue(src, (uint) src.Attributes);
+ Assert.AreEqual (expected, linked.Attributes, $"Field `{src}' pseudo attributes did not match expected");
+ }
+
+ protected virtual void VerifyPseudoAttributes (PropertyDefinition src, PropertyDefinition linked)
+ {
+ var expected = (PropertyAttributes) GetExpectedPseudoAttributeValue(src, (uint) src.Attributes);
+ Assert.AreEqual (expected, linked.Attributes, $"Property `{src}' pseudo attributes did not match expected");
+ }
+
+ protected virtual void VerifyPseudoAttributes (EventDefinition src, EventDefinition linked)
+ {
+ var expected = (EventAttributes) GetExpectedPseudoAttributeValue(src, (uint) src.Attributes);
+ Assert.AreEqual (expected, linked.Attributes, $"Event `{src}' pseudo attributes did not match expected");
+ }
+
+ protected virtual void VerifyCustomAttributes (ICustomAttributeProvider src, ICustomAttributeProvider linked)
+ {
+ var expectedAttrs = GetExpectedAttributes (src).ToList ();
+ var linkedAttrs = FilterLinkedAttributes (linked).ToList ();
+
+ Assert.That (linkedAttrs, Is.EquivalentTo (expectedAttrs), $"Custom attributes on `{src}' are not matching");
+ }
+
+ protected virtual void VerifySecurityAttributes (ICustomAttributeProvider src, ISecurityDeclarationProvider linked)
+ {
+ var expectedAttrs = GetCustomAttributeCtorValues<object> (src, nameof (KeptSecurityAttribute))
+ .Select (attr => attr.ToString ())
+ .ToList ();
+
+ var linkedAttrs = FilterLinkedSecurityAttributes (linked).ToList ();
+
+ Assert.That (linkedAttrs, Is.EquivalentTo (expectedAttrs), $"Security attributes on `{src}' are not matching");
+ }
+
+ protected virtual void VerifyArrayInitializers (MethodDefinition src, MethodDefinition linked)
+ {
+ var expectedIndicies = GetCustomAttributeCtorValues<object> (src, nameof (KeptInitializerData))
+ .Cast<int> ()
+ .ToArray ();
+
+ var expectKeptAll = src.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (KeptInitializerData) && !attr.HasConstructorArguments);
+
+ if (expectedIndicies.Length == 0 && !expectKeptAll)
+ return;
+
+ if (!src.HasBody)
+ Assert.Fail ($"`{nameof (KeptInitializerData)}` cannot be used on methods that don't have bodies");
+
+ var srcImplementationDetails = src.Module.Types.FirstOrDefault (t => string.IsNullOrEmpty (t.Namespace) && t.Name.StartsWith ("<PrivateImplementationDetails>"));
+
+ if (srcImplementationDetails == null)
+ Assert.Fail ("Could not locate <PrivateImplementationDetails> in the original assembly. Does your test use initializers?");
+
+ var linkedImplementationDetails = linked.Module.Types.FirstOrDefault (t => string.IsNullOrEmpty (t.Namespace) && t.Name.StartsWith ("<PrivateImplementationDetails>"));
+
+ if (linkedImplementationDetails == null)
+ Assert.Fail ("Could not locate <PrivateImplementationDetails> in the linked assembly");
+
+ var possibleInitializerFields = src.Body.Instructions
+ .Where (ins => IsLdtokenOnPrivateImplementationDetails (srcImplementationDetails, ins))
+ .Select (ins => ((FieldReference)ins.Operand).Resolve ())
+ .ToArray ();
+
+ if (possibleInitializerFields.Length == 0)
+ Assert.Fail ($"`{src}` does not make use of any initializers");
+
+ if (expectKeptAll) {
+ foreach (var srcField in possibleInitializerFields) {
+ var linkedField = linkedImplementationDetails.Fields.FirstOrDefault (f => f.Name == srcField.Name);
+ VerifyInitializerField (srcField, linkedField);
+ }
+ } else {
+ foreach (var index in expectedIndicies) {
+ if (index < 0 || index > possibleInitializerFields.Length)
+ Assert.Fail($"Invalid expected index `{index}` in {src}. Value must be between 0 and {expectedIndicies.Length}");
+
+ var srcField = possibleInitializerFields[index];
+ var linkedField = linkedImplementationDetails.Fields.FirstOrDefault (f => f.Name == srcField.Name);
+
+ VerifyInitializerField (srcField, linkedField);
+ }
+ }
+ }
+
+ void VerifyInitializerField (FieldDefinition src, FieldDefinition linked)
+ {
+ VerifyFieldKept (src, linked);
+ verifiedGeneratedFields.Add (linked.FullName);
+ linkedMembers.Remove (linked.FullName);
+ VerifyTypeDefinitionKept (src.FieldType.Resolve (), linked.FieldType.Resolve ());
+ linkedMembers.Remove (linked.FieldType.FullName);
+ linkedMembers.Remove (linked.DeclaringType.FullName);
+ verifiedGeneratedTypes.Add (linked.DeclaringType.FullName);
+ }
+
+ static bool IsLdtokenOnPrivateImplementationDetails (TypeDefinition privateImplementationDetails, Instruction instruction)
+ {
+ if (instruction.OpCode.Code == Code.Ldtoken && instruction.Operand is FieldReference field)
+ {
+ return field.DeclaringType.Resolve () == privateImplementationDetails;
+ }
+
+ return false;
+ }
+
+ protected static IEnumerable<string> GetExpectedAttributes (ICustomAttributeProvider original)
+ {
+ foreach (var expectedAttrs in GetCustomAttributeCtorValues<object> (original, nameof (KeptAttributeAttribute)))
+ yield return expectedAttrs.ToString ();
+
+ // The name of the generated fixed buffer type is a little tricky.
+ // Some versions of csc name it `<fieldname>e__FixedBuffer0`
+ // while mcs and other versions of csc name it `<fieldname>__FixedBuffer0`
+ if (original is TypeDefinition srcDefinition && srcDefinition.Name.Contains ("__FixedBuffer")) {
+ var name = srcDefinition.Name.Substring (1, srcDefinition.Name.IndexOf('>') - 1);
+ var fixedField = srcDefinition.DeclaringType.Fields.FirstOrDefault (f => f.Name == name);
+ if (fixedField == null)
+ Assert.Fail ($"Could not locate original fixed field for {srcDefinition}");
+
+ foreach (var additionalExpectedAttributesFromFixedField in GetCustomAttributeCtorValues<object> (fixedField, nameof (KeptAttributeOnFixedBufferTypeAttribute)))
+ yield return additionalExpectedAttributesFromFixedField.ToString ();
+
+ }
+ }
+
+ /// <summary>
+ /// Filters out some attributes that should not be taken into consideration when checking the linked result against the expected result
+ /// </summary>
+ /// <param name="linked"></param>
+ /// <returns></returns>
+ protected virtual IEnumerable<string> FilterLinkedAttributes (ICustomAttributeProvider linked)
+ {
+ foreach (var attr in linked.CustomAttributes) {
+ switch (attr.AttributeType.FullName) {
+ case "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute":
+ case "System.Runtime.CompilerServices.CompilerGeneratedAttribute":
+ continue;
+
+ // When mcs is used to compile the test cases, backing fields end up with this attribute on them
+ case "System.Diagnostics.DebuggerBrowsableAttribute":
+ continue;
+
+ case "System.Runtime.CompilerServices.CompilationRelaxationsAttribute":
+ if (linked is AssemblyDefinition)
+ continue;
+ break;
+ }
+
+ yield return attr.AttributeType.FullName;
+ }
+ }
+
+ protected virtual IEnumerable<string> FilterLinkedSecurityAttributes (ISecurityDeclarationProvider linked)
+ {
+ return linked.SecurityDeclarations
+ .SelectMany (d => d.SecurityAttributes)
+ .Select (attr => attr.AttributeType.ToString ());
+ }
+
+ void VerifyFixedBufferFields (TypeDefinition src, TypeDefinition linked)
+ {
+ var fields = src.Fields.Where (f => f.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (KeptFixedBufferAttribute)));
+
+ foreach (var field in fields) {
+ // The name of the generated fixed buffer type is a little tricky.
+ // Some versions of csc name it `<fieldname>e__FixedBuffer0`
+ // while mcs and other versions of csc name it `<fieldname>__FixedBuffer0`
+ var originalCompilerGeneratedBufferType = src.NestedTypes.FirstOrDefault (t => t.FullName.Contains ($"<{field.Name}>") && t.FullName.Contains ("__FixedBuffer"));
+ if (originalCompilerGeneratedBufferType == null)
+ Assert.Fail ($"Could not locate original compiler generated fixed buffer type for field {field}");
+
+ var linkedCompilerGeneratedBufferType = linked.NestedTypes.FirstOrDefault (t => t.Name == originalCompilerGeneratedBufferType.Name);
+ if (linkedCompilerGeneratedBufferType == null)
+ Assert.Fail ($"Missing expected type {originalCompilerGeneratedBufferType}");
+
+ // Have to verify the field before the type
+ var originalElementField = originalCompilerGeneratedBufferType.Fields.FirstOrDefault (f => f.Name == "FixedElementField");
+ if (originalElementField == null)
+ Assert.Fail ($"Could not locate original compiler generated FixedElementField on {originalCompilerGeneratedBufferType}");
+
+ var linkedField = linkedCompilerGeneratedBufferType?.Fields.FirstOrDefault (l => l.Name == originalElementField.Name);
+ VerifyFieldKept (originalElementField, linkedField);
+ verifiedGeneratedFields.Add (originalElementField.FullName);
+ linkedMembers.Remove (originalElementField.FullName);
+
+ VerifyTypeDefinitionKept(originalCompilerGeneratedBufferType, linkedCompilerGeneratedBufferType);
+ verifiedGeneratedTypes.Add(originalCompilerGeneratedBufferType.FullName);
+ }
+ }
+
+ void VerifyDelegateBackingFields (TypeDefinition src, TypeDefinition linked)
+ {
+ var expectedFieldNames = GetCustomAttributeCtorValues<string> (src, nameof (KeptDelegateCacheFieldAttribute))
+ .Select (unique => $"<>f__mg$cache{unique}")
+ .ToList ();
+
+ if (expectedFieldNames.Count == 0)
+ return;
+
+ foreach (var srcField in src.Fields) {
+ if (!expectedFieldNames.Contains (srcField.Name))
+ continue;
+
+ var linkedField = linked?.Fields.FirstOrDefault (l => l.Name == srcField.Name);
+ VerifyFieldKept (srcField, linkedField);
+ verifiedGeneratedFields.Add (srcField.FullName);
+ linkedMembers.Remove (srcField.FullName);
+ }
+ }
+
+ void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterProvider linked)
+ {
+ Assert.AreEqual (src.HasGenericParameters, linked.HasGenericParameters);
+ if (src.HasGenericParameters) {
+ for (int i = 0; i < src.GenericParameters.Count; ++i) {
+ // TODO: Verify constraints
+ VerifyCustomAttributes (src.GenericParameters [i], linked.GenericParameters [i]);
+ }
+ }
+ }
+
+ void VerifyParameters (IMethodSignature src, IMethodSignature linked)
+ {
+ Assert.AreEqual (src.HasParameters, linked.HasParameters);
+ if (src.HasParameters) {
+ for (int i = 0; i < src.Parameters.Count; ++i) {
+ VerifyCustomAttributes (src.Parameters [i], linked.Parameters [i]);
+ }
+ }
+ }
+
+ protected virtual bool ShouldMethodBeKept (MethodDefinition method)
+ {
+ var srcSignature = method.GetSignature ();
+ return ShouldBeKept (method, srcSignature) || method.DeclaringType.Module.EntryPoint == method;
+ }
+
+ protected virtual bool ShouldBeKept<T> (T member, string signature = null) where T : MemberReference, ICustomAttributeProvider
+ {
+ if (member.HasAttribute (nameof (KeptAttribute)))
+ return true;
+
+ ICustomAttributeProvider cap = (ICustomAttributeProvider)member.DeclaringType;
+ if (cap == null)
+ return false;
+
+ return GetCustomAttributeCtorValues<string> (cap, nameof (KeptMemberAttribute)).Any (a => a == (signature ?? member.Name));
+ }
+
+ protected static uint GetExpectedPseudoAttributeValue (ICustomAttributeProvider provider, uint sourceValue)
+ {
+ var removals = provider.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (RemovedPseudoAttributeAttribute)).ToArray ();
+ var adds = provider.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (AddedPseudoAttributeAttribute)).ToArray ();
+
+ return removals.Aggregate (sourceValue, (accum, item) => accum & ~((uint) item.ConstructorArguments [0].Value)) |
+ adds.Aggregate ((uint)0, (acum, item) => acum | (uint) item.ConstructorArguments [0].Value);
+ }
+
+ protected static IEnumerable<T> GetCustomAttributeCtorValues<T> (ICustomAttributeProvider provider, string attributeName) where T : class
+ {
+ return provider.CustomAttributes.
+ Where (w => w.AttributeType.Name == attributeName && w.Constructor.Parameters.Count == 1).
+ Select (l => l.ConstructorArguments [0].Value as T);
+ }
+
+ protected static IEnumerable<string> GetStringOrTypeArrayAttributeValue (CustomAttribute attribute)
+ {
+ foreach (var arg in ((CustomAttributeArgument[]) attribute.ConstructorArguments [0].Value)) {
+ if (arg.Value is TypeReference tRef)
+ yield return tRef.ToString ();
+ else
+ yield return (string) arg.Value;
+ }
+ }
+
+ protected static IEnumerable<string> GetStringArrayAttributeValue (CustomAttribute attribute)
+ {
+ return ((CustomAttributeArgument[]) attribute.ConstructorArguments [0].Value)?.Select (arg => arg.Value.ToString ());
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/CompilerOptions.cs b/test/Mono.Linker.Tests/TestCasesRunner/CompilerOptions.cs
new file mode 100644
index 000000000..7e584e904
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/CompilerOptions.cs
@@ -0,0 +1,14 @@
+using System;
+using Mono.Linker.Tests.Extensions;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class CompilerOptions {
+ public NPath OutputPath;
+ public NPath[] SourceFiles;
+ public string[] Defines;
+ public NPath[] References;
+ public NPath[] Resources;
+ public string[] AdditionalArguments;
+ public string CompilerToUse;
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs b/test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs
new file mode 100644
index 000000000..8b3baf0e3
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs
@@ -0,0 +1,17 @@
+using Mono.Cecil;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public static class ExpectationsProvider {
+
+ public static bool IsAssemblyAssertion (CustomAttribute attr)
+ {
+ return attr.AttributeType.Name == nameof (KeptAssemblyAttribute) || attr.AttributeType.Name == nameof (RemovedAssemblyAttribute);
+ }
+
+ public static bool IsSymbolAssertion (CustomAttribute attr)
+ {
+ return attr.AttributeType.Name == nameof (KeptSymbolsAttribute) || attr.AttributeType.Name == nameof (RemovedSymbolsAttribute);
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/FormattingUtils.cs b/test/Mono.Linker.Tests/TestCasesRunner/FormattingUtils.cs
new file mode 100644
index 000000000..97c14abb2
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/FormattingUtils.cs
@@ -0,0 +1,59 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public static class FormattingUtils {
+ public static string FormatSequenceCompareFailureMessage (IEnumerable<string> actual, IEnumerable<string> expected)
+ {
+ var builder = new StringBuilder ();
+ builder.AppendLine ("---------------");
+ builder.AppendLine ($"Expected/Original (Total : {expected.Count ()})");
+ builder.AppendLine ("---------------");
+ // Format in a quoted array form for easier copying into a expected sequence attribute
+ builder.AppendLine (expected.Select (c => $"\"{c}\",").AggregateWithNewLine ());
+ builder.AppendLine ("---------------");
+ builder.AppendLine ($"Actual/Linked (Total : {actual.Count ()})");
+ builder.AppendLine ("---------------");
+ // Format in a quoted array form for easier copying into a expected sequence attribute
+ builder.AppendLine (actual.Select(c => $"\"{c}\",").AggregateWithNewLine ());
+ builder.AppendLine ("---------------");
+ return builder.ToString ();
+ }
+
+ public static string FormatSequenceCompareFailureMessage2 (IEnumerable<string> actual, IEnumerable<string> expected, IEnumerable<string> original)
+ {
+ var builder = new StringBuilder ();
+ builder.AppendLine ("---------------");
+ builder.AppendLine ($"Expected (Total : {expected.Count ()})");
+ builder.AppendLine ("---------------");
+ // Format in a quoted array form for easier copying into a expected sequence attribute
+ builder.AppendLine (expected.Select(c => $"\"{c}\",").AggregateWithNewLine ());
+ builder.AppendLine ("---------------");
+ builder.AppendLine ($"Actual/Linked (Total : {actual.Count ()})");
+ builder.AppendLine ("---------------");
+ // Format in a quoted array form for easier copying into a expected sequence attribute
+ builder.AppendLine (actual.Select(c => $"\"{c}\",").AggregateWithNewLine ());
+ builder.AppendLine ("---------------");
+ builder.AppendLine ($"Original (Total : {original.Count()})");
+ builder.AppendLine ("---------------");
+ // Format in a quoted array form for easier copying into a expected sequence attribute
+ builder.AppendLine (original.Select(c => $"\"{c}\",").AggregateWithNewLine ());
+ builder.AppendLine ("---------------");
+ return builder.ToString ();
+ }
+
+ private static string AggregateWithNewLine (this IEnumerable<string> elements)
+ {
+ return elements.AggregateWith (System.Environment.NewLine);
+ }
+
+ private static string AggregateWith (this IEnumerable<string> elements, string separator)
+ {
+ if (elements.Any ())
+ return elements.Aggregate ((buff, s) => buff + separator + s);
+
+ return string.Empty;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs b/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs
new file mode 100644
index 000000000..517bcb273
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/ILCompiler.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using Mono.Linker.Tests.Extensions;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class ILCompiler {
+ private readonly string _ilasmExecutable;
+
+ public ILCompiler ()
+ {
+ _ilasmExecutable = Environment.OSVersion.Platform == PlatformID.Win32NT ? LocateIlasmOnWindows ().ToString () : "ilasm";
+ }
+
+ public ILCompiler (string ilasmExecutable)
+ {
+ _ilasmExecutable = ilasmExecutable;
+ }
+
+ public NPath Compile (CompilerOptions options)
+ {
+ var capturedOutput = new List<string> ();
+ var process = new Process ();
+ SetupProcess (process, options);
+ process.StartInfo.RedirectStandardOutput = true;
+ process.OutputDataReceived += (sender, args) => capturedOutput.Add (args.Data);
+ process.Start ();
+ process.BeginOutputReadLine ();
+ process.WaitForExit ();
+
+ if (process.ExitCode != 0)
+ {
+ Assert.Fail($"Failed to compile IL assembly : {options.OutputPath}\n{capturedOutput.Aggregate ((buff, s) => buff + Environment.NewLine + s)}");
+ }
+
+ return options.OutputPath;
+ }
+
+ protected virtual void SetupProcess (Process process, CompilerOptions options)
+ {
+ process.StartInfo.FileName = _ilasmExecutable;
+ process.StartInfo.Arguments = BuildArguments (options);
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.CreateNoWindow = true;
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ }
+
+ private string BuildArguments (CompilerOptions options)
+ {
+ var args = new StringBuilder();
+ args.Append(options.OutputPath.ExtensionWithDot == ".dll" ? "/dll" : "/exe");
+ args.Append($" /out:{options.OutputPath.InQuotes ()}");
+ args.Append($" {options.SourceFiles.Aggregate (string.Empty, (buff, file) => $"{buff} {file.InQuotes ()}")}");
+ return args.ToString ();
+ }
+
+ public static NPath LocateIlasmOnWindows ()
+ {
+ if (Environment.OSVersion.Platform != PlatformID.Win32NT)
+ throw new InvalidOperationException ("This method should only be called on windows");
+
+ var possiblePath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory ().ToNPath ().Combine ("ilasm.exe");
+ if (possiblePath.FileExists ())
+ return possiblePath;
+
+ throw new InvalidOperationException ("Could not locate a ilasm.exe executable");
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkXmlHelpers.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkXmlHelpers.cs
new file mode 100644
index 000000000..c7e70cf71
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkXmlHelpers.cs
@@ -0,0 +1,30 @@
+using System.Text;
+using Mono.Cecil;
+using Mono.Linker.Tests.Extensions;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public static class LinkXmlHelpers {
+ public static void WriteXmlFileToPreserveEntryPoint (NPath targetProgram, NPath xmlFile)
+ {
+ using (var assembly = AssemblyDefinition.ReadAssembly (targetProgram.ToString ())) {
+ var method = assembly.EntryPoint;
+
+ var sb = new StringBuilder ();
+ sb.AppendLine ("<linker>");
+
+ sb.AppendLine (" <assembly fullname=\"" + assembly.FullName + "\">");
+
+ if (method != null) {
+ sb.AppendLine (" <type fullname=\"" + method.DeclaringType.FullName + "\">");
+ sb.AppendLine (" <method name=\"" + method.Name + "\"/>");
+ sb.AppendLine (" </type>");
+ }
+
+ sb.AppendLine (" </assembly>");
+
+ sb.AppendLine ("</linker>");
+ xmlFile.WriteAllText (sb.ToString ());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs
new file mode 100644
index 000000000..2d05f6d09
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkedTestCaseResult.cs
@@ -0,0 +1,19 @@
+using Mono.Linker.Tests.Extensions;
+using Mono.Linker.Tests.TestCases;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class LinkedTestCaseResult {
+ public readonly TestCase TestCase;
+ public readonly NPath InputAssemblyPath;
+ public readonly NPath OutputAssemblyPath;
+ public readonly NPath ExpectationsAssemblyPath;
+
+ public LinkedTestCaseResult (TestCase testCase, NPath inputAssemblyPath, NPath outputAssemblyPath, NPath expectationsAssemblyPath)
+ {
+ TestCase = testCase;
+ InputAssemblyPath = inputAssemblyPath;
+ OutputAssemblyPath = outputAssemblyPath;
+ ExpectationsAssemblyPath = expectationsAssemblyPath;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkerArgumentBuilder.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkerArgumentBuilder.cs
new file mode 100644
index 000000000..98f93d782
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkerArgumentBuilder.cs
@@ -0,0 +1,180 @@
+using System.Collections.Generic;
+using Mono.Linker.Tests.Extensions;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class LinkerArgumentBuilder {
+ private readonly List<string> _arguments = new List<string> ();
+ private readonly TestCaseMetadaProvider _metadaProvider;
+
+ public LinkerArgumentBuilder (TestCaseMetadaProvider metadaProvider)
+ {
+ _metadaProvider = metadaProvider;
+ }
+
+ public virtual void AddSearchDirectory (NPath directory)
+ {
+ Append ("-d");
+ Append (directory.ToString ());
+ }
+
+ public virtual void AddOutputDirectory (NPath directory)
+ {
+ Append ("-o");
+ Append (directory.ToString ());
+ }
+
+ public virtual void AddLinkXmlFile (NPath path)
+ {
+ Append ("-x");
+ Append (path.ToString ());
+ }
+
+ public virtual void AddResponseFile (NPath path)
+ {
+ Append ($"@{path}");
+ }
+
+ public virtual void AddCoreLink (string value)
+ {
+ Append ("-c");
+ Append (value);
+ }
+
+ public virtual void AddUserLink (string value)
+ {
+ Append ("-u");
+ Append (value);
+ }
+
+ public virtual void LinkFromAssembly (string fileName)
+ {
+ Append ("-a");
+ Append (fileName);
+ }
+
+ public virtual void LinkFromPublicAndFamily (string fileName)
+ {
+ Append ("-r");
+ Append (fileName);
+ }
+
+ public virtual void IncludeBlacklist (bool value)
+ {
+ Append ("-z");
+ Append (value ? "true" : "false");
+ }
+
+ public virtual void AddIl8n (string value)
+ {
+ Append ("-l");
+ Append (value);
+ }
+
+ public virtual void AddKeepTypeForwarderOnlyAssemblies (string value)
+ {
+ if (bool.Parse (value))
+ Append ("-t");
+ }
+
+ public virtual void AddLinkSymbols (string value)
+ {
+ Append ("-b");
+ Append (value);
+ }
+
+ public virtual void AddKeepDebugMembers (string value)
+ {
+ Append ("-v");
+ Append (value);
+ }
+
+ public virtual void AddAssemblyAction (string action, string assembly)
+ {
+ Append ("-p");
+ Append (action);
+ Append (assembly);
+ }
+
+ public virtual void AddSkipUnresolved (bool skipUnresolved)
+ {
+ if (skipUnresolved) {
+ Append ("--skip-unresolved");
+ Append ("true");
+ }
+ }
+
+ public virtual void AddStripResources (bool stripResources)
+ {
+ if (!stripResources) {
+ Append ("--strip-resources");
+ Append ("false");
+ }
+ }
+
+ public string [] ToArgs ()
+ {
+ return _arguments.ToArray ();
+ }
+
+ protected void Append (string arg)
+ {
+ _arguments.Add (arg);
+ }
+
+ public virtual void AddAdditionalArgument (string flag, string [] values)
+ {
+ Append (flag);
+ if (values != null) {
+ foreach (var val in values)
+ Append (val);
+ }
+ }
+
+ public virtual void ProcessTestInputAssembly (NPath inputAssemblyPath)
+ {
+ if (_metadaProvider.LinkPublicAndFamily ())
+ LinkFromPublicAndFamily (inputAssemblyPath.ToString ());
+ else
+ LinkFromAssembly (inputAssemblyPath.ToString ());
+ }
+
+ public virtual void ProcessOptions (TestCaseLinkerOptions options)
+ {
+ if (options.CoreAssembliesAction != null)
+ AddCoreLink (options.CoreAssembliesAction);
+
+ if (options.UserAssembliesAction != null)
+ AddUserLink (options.UserAssembliesAction);
+
+ if (options.AssembliesAction != null) {
+ foreach (var entry in options.AssembliesAction)
+ AddAssemblyAction (entry.Key, entry.Value);
+ }
+
+ // Running the blacklist step causes a ton of stuff to be preserved. That's good for normal use cases, but for
+ // our test cases that pollutes the results
+ IncludeBlacklist (options.IncludeBlacklistStep);
+
+ if (!string.IsNullOrEmpty (options.Il8n))
+ AddIl8n (options.Il8n);
+
+ if (!string.IsNullOrEmpty (options.KeepTypeForwarderOnlyAssemblies))
+ AddKeepTypeForwarderOnlyAssemblies (options.KeepTypeForwarderOnlyAssemblies);
+
+ if (!string.IsNullOrEmpty (options.LinkSymbols))
+ AddLinkSymbols (options.LinkSymbols);
+
+ if (!string.IsNullOrEmpty (options.KeepDebugMembers))
+ AddKeepDebugMembers (options.KeepDebugMembers);
+
+ AddSkipUnresolved (options.SkipUnresolved);
+
+ AddStripResources (options.StripResources);
+
+ // Unity uses different argument format and needs to be able to translate to their format. In order to make that easier
+ // we keep the information in flag + values format for as long as we can so that this information doesn't have to be parsed out of a single string
+ foreach (var additionalArgument in options.AdditionalArguments)
+ AddAdditionalArgument (additionalArgument.Key, additionalArgument.Value);
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
new file mode 100644
index 000000000..f76898873
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
@@ -0,0 +1,8 @@
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class LinkerDriver {
+ public virtual void Link (string [] args)
+ {
+ new Driver (args).Run ();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ManagedCompilationResult.cs b/test/Mono.Linker.Tests/TestCasesRunner/ManagedCompilationResult.cs
new file mode 100644
index 000000000..ccce993f9
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/ManagedCompilationResult.cs
@@ -0,0 +1,15 @@
+using Mono.Linker.Tests.Extensions;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class ManagedCompilationResult {
+ public ManagedCompilationResult (NPath inputAssemblyPath, NPath expectationsAssemblyPath)
+ {
+ InputAssemblyPath = inputAssemblyPath;
+ ExpectationsAssemblyPath = expectationsAssemblyPath;
+ }
+
+ public NPath InputAssemblyPath { get; }
+
+ public NPath ExpectationsAssemblyPath { get; }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ObjectFactory.cs b/test/Mono.Linker.Tests/TestCasesRunner/ObjectFactory.cs
new file mode 100644
index 000000000..71d1c3859
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/ObjectFactory.cs
@@ -0,0 +1,31 @@
+using Mono.Cecil;
+using Mono.Linker.Tests.TestCases;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class ObjectFactory {
+ public virtual TestCaseSandbox CreateSandbox (TestCase testCase)
+ {
+ return new TestCaseSandbox (testCase);
+ }
+
+ public virtual TestCaseCompiler CreateCompiler (TestCaseSandbox sandbox, TestCaseMetadaProvider metadataProvider)
+ {
+ return new TestCaseCompiler (sandbox, metadataProvider);
+ }
+
+ public virtual LinkerDriver CreateLinker ()
+ {
+ return new LinkerDriver ();
+ }
+
+ public virtual TestCaseMetadaProvider CreateMetadataProvider (TestCase testCase, AssemblyDefinition fullTestCaseAssemblyDefinition)
+ {
+ return new TestCaseMetadaProvider (testCase, fullTestCaseAssemblyDefinition);
+ }
+
+ public virtual LinkerArgumentBuilder CreateLinkerArgumentBuilder (TestCaseMetadaProvider metadataProvider)
+ {
+ return new LinkerArgumentBuilder (metadataProvider);
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs b/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs
new file mode 100644
index 000000000..dd3d5e37c
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/PeVerifier.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Microsoft.Win32;
+using Mono.Cecil;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Extensions;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class PeVerifier {
+ private readonly string _peExecutable;
+
+ public PeVerifier ()
+ {
+ _peExecutable = Environment.OSVersion.Platform == PlatformID.Win32NT ? FindPeExecutableFromRegistry ().ToString () : "pedump";
+ }
+
+ public PeVerifier (string peExecutable)
+ {
+ _peExecutable = peExecutable;
+ }
+
+ public virtual void Check (LinkedTestCaseResult linkResult, AssemblyDefinition original)
+ {
+ bool skipCheckEntirely;
+ HashSet<string> assembliesToSkip;
+ ProcessSkipAttributes (linkResult, original, out skipCheckEntirely, out assembliesToSkip);
+
+ if (skipCheckEntirely)
+ return;
+
+ foreach (var file in linkResult.OutputAssemblyPath.Parent.Files ()) {
+ if (file.ExtensionWithDot != ".exe" && file.ExtensionWithDot != ".dll")
+ continue;
+
+ // Always skip the I18N assemblies, for some reason they end up in the output directory on OSX.
+ // verification of these fails due to native pointers
+ if (file.FileName.StartsWith ("I18N"))
+ continue;
+
+ if (assembliesToSkip.Contains (file.FileName))
+ continue;
+
+ CheckAssembly (file);
+ }
+ }
+
+ private void ProcessSkipAttributes (LinkedTestCaseResult linkResult, AssemblyDefinition original, out bool skipCheckEntirely, out HashSet<string> assembliesToSkip)
+ {
+ var peVerifyAttrs = original.MainModule.GetType (linkResult.TestCase.ReconstructedFullTypeName).CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SkipPeVerifyAttribute));
+ skipCheckEntirely = false;
+ assembliesToSkip = new HashSet<string> ();
+ foreach (var attr in peVerifyAttrs) {
+ var ctorArg = attr.ConstructorArguments.FirstOrDefault ();
+
+ if (!attr.HasConstructorArguments) {
+ skipCheckEntirely = true;
+ } else if (ctorArg.Type.Name == nameof (SkipPeVerifyForToolchian)) {
+ var skipToolchain = (SkipPeVerifyForToolchian)ctorArg.Value;
+
+ if (skipToolchain == SkipPeVerifyForToolchian.Pedump) {
+ if (Environment.OSVersion.Platform != PlatformID.Win32NT)
+ skipCheckEntirely = true;
+ }
+ else
+ throw new ArgumentException ($"Unhandled platform and toolchain values of {Environment.OSVersion.Platform} and {skipToolchain}");
+ } else if (ctorArg.Type.Name == nameof (String)) {
+ assembliesToSkip.Add ((string)ctorArg.Value);
+ } else {
+ throw new ArgumentException ($"Unhandled constructor argument type of {ctorArg.Type} on {nameof (SkipPeVerifyAttribute)}");
+ }
+ }
+ }
+
+ private void CheckAssembly (NPath assemblyPath)
+ {
+ var capturedOutput = new List<string> ();
+ var process = new Process ();
+ SetupProcess (process, assemblyPath);
+ process.StartInfo.RedirectStandardOutput = true;
+ process.OutputDataReceived += (sender, args) => capturedOutput.Add (args.Data);
+ process.Start ();
+ process.BeginOutputReadLine ();
+ process.WaitForExit ();
+
+ if (process.ExitCode != 0) {
+ Assert.Fail ($"Invalid IL detected in {assemblyPath}\n{capturedOutput.Aggregate ((buff, s) => buff + Environment.NewLine + s)}");
+ }
+ }
+
+ protected virtual void SetupProcess (Process process, NPath assemblyPath)
+ {
+ var exeArgs = Environment.OSVersion.Platform == PlatformID.Win32NT ? $"/nologo {assemblyPath.InQuotes ()}" : $"--verify metadata,code {assemblyPath.InQuotes ()}";
+ process.StartInfo.FileName = _peExecutable;
+ process.StartInfo.Arguments = exeArgs;
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.CreateNoWindow = true;
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+
+ if (Environment.OSVersion.Platform != PlatformID.Win32NT) {
+ process.StartInfo.Environment ["MONO_PATH"] = assemblyPath.Parent.ToString ();
+ }
+ }
+
+ public static NPath FindPeExecutableFromRegistry ()
+ {
+ if (Environment.OSVersion.Platform != PlatformID.Win32NT)
+ throw new InvalidOperationException ("This method should only be called on windows");
+
+ NPath result;
+ if (TryFindPeExecutableFromRegustrySubfolder ("NETFXSDK", out result))
+ return result;
+ if (TryFindPeExecutableFromRegustrySubfolder ("Windows", out result))
+ return result;
+
+ throw new InvalidOperationException ("Could not locate a peverify.exe executable");
+ }
+
+ private static bool TryFindPeExecutableFromRegustrySubfolder (string subfolder, out NPath peVerifyPath)
+ {
+ var keyPath = $"SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft SDKs\\{subfolder}";
+ var key = Registry.LocalMachine.OpenSubKey (keyPath);
+
+ foreach (var sdkKeyName in key.GetSubKeyNames ().OrderBy (name => new Version (name.TrimStart ('v').TrimEnd ('A'))).Reverse ()) {
+ var sdkKey = Registry.LocalMachine.OpenSubKey ($"{keyPath}\\{sdkKeyName}");
+
+ var sdkDir = (string)sdkKey.GetValue ("InstallationFolder");
+ if (string.IsNullOrEmpty (sdkDir))
+ continue;
+
+ var binDir = sdkDir.ToNPath ().Combine ("bin");
+ if (!binDir.Exists ())
+ continue;
+
+ foreach (var netSdkDirs in binDir.Directories ().OrderBy (dir => dir.FileName)) {
+ peVerifyPath = netSdkDirs.Combine ("PEVerify.exe");
+ if (peVerifyPath.FileExists ())
+ return true;
+ }
+ }
+ peVerifyPath = null;
+ return false;
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
new file mode 100644
index 000000000..545e381cd
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs
@@ -0,0 +1,629 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Extensions;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class ResultChecker
+ {
+ readonly BaseAssemblyResolver _originalsResolver;
+ readonly BaseAssemblyResolver _linkedResolver;
+ readonly ReaderParameters _originalReaderParameters;
+ readonly ReaderParameters _linkedReaderParameters;
+ readonly PeVerifier _peVerifier;
+
+ public ResultChecker ()
+ : this(new TestCaseAssemblyResolver (), new TestCaseAssemblyResolver (), new PeVerifier (),
+ new ReaderParameters
+ {
+ SymbolReaderProvider = new DefaultSymbolReaderProvider (false)
+ },
+ new ReaderParameters
+ {
+ SymbolReaderProvider = new DefaultSymbolReaderProvider (false)
+ })
+ {
+ }
+
+ public ResultChecker (BaseAssemblyResolver originalsResolver, BaseAssemblyResolver linkedResolver, PeVerifier peVerifier,
+ ReaderParameters originalReaderParameters, ReaderParameters linkedReaderParameters)
+ {
+ _originalsResolver = originalsResolver;
+ _linkedResolver = linkedResolver;
+ _peVerifier = peVerifier;
+ _originalReaderParameters = originalReaderParameters;
+ _linkedReaderParameters = linkedReaderParameters;
+ }
+
+ public virtual void Check (LinkedTestCaseResult linkResult)
+ {
+ Assert.IsTrue (linkResult.OutputAssemblyPath.FileExists (), $"The linked output assembly was not found. Expected at {linkResult.OutputAssemblyPath}");
+
+ InitializeResolvers (linkResult);
+
+ try
+ {
+ var original = ResolveOriginalsAssembly (linkResult.ExpectationsAssemblyPath.FileNameWithoutExtension);
+ PerformOutputAssemblyChecks (original, linkResult.OutputAssemblyPath.Parent);
+ PerformOutputSymbolChecks (original, linkResult.OutputAssemblyPath.Parent);
+
+ var linked = ResolveLinkedAssembly (linkResult.OutputAssemblyPath.FileNameWithoutExtension);
+
+ CreateAssemblyChecker (original, linked).Verify ();
+
+ VerifyLinkingOfOtherAssemblies (original);
+
+ _peVerifier.Check (linkResult, original);
+
+ AdditionalChecking (linkResult, original, linked);
+ }
+ finally
+ {
+ _originalsResolver.Dispose ();
+ _linkedResolver.Dispose ();
+ }
+ }
+
+ protected virtual AssemblyChecker CreateAssemblyChecker (AssemblyDefinition original, AssemblyDefinition linked)
+ {
+ return new AssemblyChecker (original, linked);
+ }
+
+ void InitializeResolvers (LinkedTestCaseResult linkedResult)
+ {
+ _originalsResolver.AddSearchDirectory (linkedResult.ExpectationsAssemblyPath.Parent.ToString ());
+ _linkedResolver.AddSearchDirectory (linkedResult.OutputAssemblyPath.Parent.ToString ());
+ }
+
+ protected AssemblyDefinition ResolveLinkedAssembly (string assemblyName)
+ {
+ var cleanAssemblyName = assemblyName;
+ if (assemblyName.EndsWith(".exe") || assemblyName.EndsWith(".dll"))
+ cleanAssemblyName = System.IO.Path.GetFileNameWithoutExtension (assemblyName);
+ return _linkedResolver.Resolve (new AssemblyNameReference (cleanAssemblyName, null), _linkedReaderParameters);
+ }
+
+ protected AssemblyDefinition ResolveOriginalsAssembly (string assemblyName)
+ {
+ var cleanAssemblyName = assemblyName;
+ if (assemblyName.EndsWith (".exe") || assemblyName.EndsWith (".dll"))
+ cleanAssemblyName = Path.GetFileNameWithoutExtension (assemblyName);
+ return _originalsResolver.Resolve (new AssemblyNameReference (cleanAssemblyName, null), _originalReaderParameters);
+ }
+
+ void PerformOutputAssemblyChecks (AssemblyDefinition original, NPath outputDirectory)
+ {
+ var assembliesToCheck = original.MainModule.Types.SelectMany (t => t.CustomAttributes).Where (attr => ExpectationsProvider.IsAssemblyAssertion(attr));
+
+ foreach (var assemblyAttr in assembliesToCheck) {
+ var name = (string) assemblyAttr.ConstructorArguments.First ().Value;
+ var expectedPath = outputDirectory.Combine (name);
+
+ if (assemblyAttr.AttributeType.Name == nameof (RemovedAssemblyAttribute))
+ Assert.IsFalse (expectedPath.FileExists (), $"Expected the assembly {name} to not exist in {outputDirectory}, but it did");
+ else if (assemblyAttr.AttributeType.Name == nameof (KeptAssemblyAttribute))
+ Assert.IsTrue (expectedPath.FileExists (), $"Expected the assembly {name} to exist in {outputDirectory}, but it did not");
+ else
+ throw new NotImplementedException($"Unknown assembly assertion of type {assemblyAttr.AttributeType}");
+ }
+ }
+
+ void PerformOutputSymbolChecks (AssemblyDefinition original, NPath outputDirectory)
+ {
+ var symbolFilesToCheck = original.MainModule.Types.SelectMany (t => t.CustomAttributes).Where (ExpectationsProvider.IsSymbolAssertion);
+
+ foreach (var symbolAttr in symbolFilesToCheck) {
+ if (symbolAttr.AttributeType.Name == nameof (RemovedSymbolsAttribute))
+ VerifyRemovedSymbols (symbolAttr, outputDirectory);
+ else if (symbolAttr.AttributeType.Name == nameof (KeptSymbolsAttribute))
+ VerifyKeptSymbols (symbolAttr);
+ else
+ throw new NotImplementedException($"Unknown symbol file assertion of type {symbolAttr.AttributeType}");
+ }
+ }
+
+ void VerifyKeptSymbols (CustomAttribute symbolsAttribute)
+ {
+ var assemblyName = (string) symbolsAttribute.ConstructorArguments [0].Value;
+ var originalAssembly = ResolveOriginalsAssembly (assemblyName);
+ var linkedAssembly = ResolveLinkedAssembly (assemblyName);
+
+ if (linkedAssembly.MainModule.SymbolReader == null)
+ Assert.Fail ($"Missing symbols for assembly `{linkedAssembly.MainModule.FileName}`");
+
+ if (linkedAssembly.MainModule.SymbolReader.GetType () != originalAssembly.MainModule.SymbolReader.GetType ())
+ Assert.Fail ($"Expected symbol provider of type `{originalAssembly.MainModule.SymbolReader}`, but was `{linkedAssembly.MainModule.SymbolReader}`");
+ }
+
+ void VerifyRemovedSymbols (CustomAttribute symbolsAttribute, NPath outputDirectory)
+ {
+ var assemblyName = (string) symbolsAttribute.ConstructorArguments [0].Value;
+ try
+ {
+ var linkedAssembly = ResolveLinkedAssembly (assemblyName);
+
+ if (linkedAssembly.MainModule.SymbolReader != null)
+ Assert.Fail ($"Expected no symbols to be found for assembly `{linkedAssembly.MainModule.FileName}`, however, symbols were found of type {linkedAssembly.MainModule.SymbolReader}");
+ } catch (AssemblyResolutionException) {
+ // If we failed to resolve, then the entire assembly may be gone.
+ // The assembly being gone confirms that embedded pdbs were removed, but technically, for the other symbol types, the symbol file could still exist on disk
+ // let's check to make sure that it does not.
+ var possibleSymbolFilePath = outputDirectory.Combine ($"{assemblyName}").ChangeExtension ("pdb");
+ if (possibleSymbolFilePath.Exists ())
+ Assert.Fail ($"Expected no symbols to be found for assembly `{assemblyName}`, however, a symbol file was found at {possibleSymbolFilePath}");
+
+ possibleSymbolFilePath = outputDirectory.Combine ($"{assemblyName}.mdb");
+ if (possibleSymbolFilePath.Exists ())
+ Assert.Fail ($"Expected no symbols to be found for assembly `{assemblyName}`, however, a symbol file was found at {possibleSymbolFilePath}");
+ }
+ }
+
+ protected virtual void AdditionalChecking (LinkedTestCaseResult linkResult, AssemblyDefinition original, AssemblyDefinition linked)
+ {
+ }
+
+ void VerifyLinkingOfOtherAssemblies (AssemblyDefinition original)
+ {
+ var checks = BuildOtherAssemblyCheckTable (original);
+
+ try {
+ foreach (var assemblyName in checks.Keys) {
+ using (var linkedAssembly = ResolveLinkedAssembly (assemblyName)) {
+ foreach (var checkAttrInAssembly in checks [assemblyName])
+ {
+ var attributeTypeName = checkAttrInAssembly.AttributeType.Name;
+ if (attributeTypeName == nameof (KeptAllTypesAndMembersInAssemblyAttribute)) {
+ VerifyKeptAllTypesAndMembersInAssembly (linkedAssembly);
+ continue;
+ }
+
+ if (attributeTypeName == nameof (KeptAttributeInAssemblyAttribute)) {
+ VerifyKeptAttributeInAssembly (checkAttrInAssembly, linkedAssembly);
+ continue;
+ }
+
+ if (attributeTypeName == nameof (RemovedAttributeInAssembly)) {
+ VerifyRemovedAttributeInAssembly (checkAttrInAssembly, linkedAssembly);
+ continue;
+ }
+
+ var expectedTypeName = checkAttrInAssembly.ConstructorArguments [1].Value.ToString ();
+ var linkedType = linkedAssembly.MainModule.GetType (expectedTypeName);
+
+ if (linkedType == null && linkedAssembly.MainModule.HasExportedTypes) {
+ linkedType = linkedAssembly.MainModule.ExportedTypes
+ .FirstOrDefault (exported => exported.FullName == expectedTypeName)
+ ?.Resolve ();
+ }
+
+ switch (attributeTypeName) {
+ case nameof (RemovedTypeInAssemblyAttribute):
+ if (linkedType != null)
+ Assert.Fail ($"Type `{expectedTypeName}' should have been removed");
+ GetOriginalTypeFromInAssemblyAttribute (checkAttrInAssembly);
+ break;
+ case nameof (KeptTypeInAssemblyAttribute):
+ if (linkedType == null)
+ Assert.Fail ($"Type `{expectedTypeName}' should have been kept");
+ break;
+ case nameof (RemovedInterfaceOnTypeInAssemblyAttribute):
+ if (linkedType == null)
+ Assert.Fail ($"Type `{expectedTypeName}' should have been kept");
+ VerifyRemovedInterfaceOnTypeInAssembly (checkAttrInAssembly, linkedType);
+ break;
+ case nameof (KeptInterfaceOnTypeInAssemblyAttribute):
+ if (linkedType == null)
+ Assert.Fail ($"Type `{expectedTypeName}' should have been kept");
+ VerifyKeptInterfaceOnTypeInAssembly (checkAttrInAssembly, linkedType);
+ break;
+ case nameof (RemovedMemberInAssemblyAttribute):
+ if (linkedType == null)
+ continue;
+
+ VerifyRemovedMemberInAssembly (checkAttrInAssembly, linkedType);
+ break;
+ case nameof (KeptBaseOnTypeInAssemblyAttribute):
+ if (linkedType == null)
+ Assert.Fail ($"Type `{expectedTypeName}' should have been kept");
+ VerifyKeptBaseOnTypeInAssembly (checkAttrInAssembly, linkedType);
+ break;
+ case nameof (KeptMemberInAssemblyAttribute):
+ if (linkedType == null)
+ Assert.Fail ($"Type `{expectedTypeName}' should have been kept");
+
+ VerifyKeptMemberInAssembly (checkAttrInAssembly, linkedType);
+ break;
+ case nameof (RemovedForwarderAttribute):
+ if (linkedAssembly.MainModule.ExportedTypes.Any (l => l.Name == expectedTypeName))
+ Assert.Fail ($"Forwarder `{expectedTypeName}' should have been removed");
+
+ break;
+ case nameof (KeptResourceInAssemblyAttribute):
+ VerifyKeptResourceInAssembly (checkAttrInAssembly);
+ break;
+ case nameof (RemovedResourceInAssemblyAttribute):
+ VerifyRemovedResourceInAssembly (checkAttrInAssembly);
+ break;
+ case nameof (KeptReferencesInAssemblyAttribute):
+ VerifyKeptReferencesInAssembly (checkAttrInAssembly);
+ break;
+ default:
+ UnhandledOtherAssemblyAssertion (expectedTypeName, checkAttrInAssembly, linkedType);
+ break;
+ }
+ }
+ }
+ }
+ } catch (AssemblyResolutionException e) {
+ Assert.Fail ($"Failed to resolve linked assembly `{e.AssemblyReference.Name}`. It must not exist in any of the output directories:\n\t{_linkedResolver.GetSearchDirectories ().Aggregate ((buff, s) => $"{buff}\n\t{s}")}\n");
+ }
+ }
+
+ void VerifyKeptAttributeInAssembly (CustomAttribute inAssemblyAttribute, AssemblyDefinition linkedAssembly)
+ {
+ VerifyAttributeInAssembly(inAssemblyAttribute, linkedAssembly, VerifyCustomAttributeKept);
+ }
+
+ void VerifyRemovedAttributeInAssembly (CustomAttribute inAssemblyAttribute, AssemblyDefinition linkedAssembly)
+ {
+ VerifyAttributeInAssembly (inAssemblyAttribute, linkedAssembly, VerifyCustomAttributeRemoved);
+ }
+
+ void VerifyAttributeInAssembly (CustomAttribute inAssemblyAttribute, AssemblyDefinition linkedAssembly, Action<ICustomAttributeProvider, string> assertExpectedAttribute)
+ {
+ var assemblyName = (string) inAssemblyAttribute.ConstructorArguments [0].Value;
+ string expectedAttributeTypeName;
+ var attributeTypeOrTypeName = inAssemblyAttribute.ConstructorArguments [1].Value;
+ if (attributeTypeOrTypeName is TypeReference typeReference) {
+ expectedAttributeTypeName = typeReference.FullName;
+ } else {
+ expectedAttributeTypeName = attributeTypeOrTypeName.ToString ();
+ }
+
+ if (inAssemblyAttribute.ConstructorArguments.Count == 2) {
+ // Assembly
+ assertExpectedAttribute (linkedAssembly, expectedAttributeTypeName);
+ return;
+ }
+
+ // We are asserting on type or member
+ var typeOrTypeName = inAssemblyAttribute.ConstructorArguments [2].Value;
+ var originalType = GetOriginalTypeFromInAssemblyAttribute (inAssemblyAttribute.ConstructorArguments[0].Value.ToString (), typeOrTypeName);
+ if (originalType == null)
+ Assert.Fail ($"Invalid test assertion. The original `{assemblyName}` does not contain a type `{typeOrTypeName}`");
+
+ var linkedType = linkedAssembly.MainModule.GetType (originalType.FullName);
+ if (linkedType == null)
+ Assert.Fail ($"Missing expected type `{typeOrTypeName}` in `{assemblyName}`");
+
+ if (inAssemblyAttribute.ConstructorArguments.Count == 3) {
+ assertExpectedAttribute (linkedType, expectedAttributeTypeName);
+ return;
+ }
+
+ // we are asserting on a member
+ string memberName = (string) inAssemblyAttribute.ConstructorArguments [3].Value;
+
+ // We will find the matching type from the original assembly first that way we can confirm
+ // that the name defined in the attribute corresponds to a member that actually existed
+ var originalFieldMember = originalType.Fields.FirstOrDefault (m => m.Name == memberName);
+ if (originalFieldMember != null) {
+ var linkedField = linkedType.Fields.FirstOrDefault (m => m.Name == memberName);
+ if (linkedField == null)
+ Assert.Fail ($"Field `{memberName}` on Type `{originalType}` should have been kept");
+
+ assertExpectedAttribute (linkedField, expectedAttributeTypeName);
+ return;
+ }
+
+ var originalPropertyMember = originalType.Properties.FirstOrDefault (m => m.Name == memberName);
+ if (originalPropertyMember != null) {
+ var linkedProperty = linkedType.Properties.FirstOrDefault (m => m.Name == memberName);
+ if (linkedProperty == null)
+ Assert.Fail ($"Property `{memberName}` on Type `{originalType}` should have been kept");
+
+ assertExpectedAttribute (linkedProperty, expectedAttributeTypeName);
+ return;
+ }
+
+ var originalMethodMember = originalType.Methods.FirstOrDefault (m => m.GetSignature () == memberName);
+ if (originalMethodMember != null) {
+ var linkedMethod = linkedType.Methods.FirstOrDefault (m => m.GetSignature () == memberName);
+ if (linkedMethod == null)
+ Assert.Fail ($"Method `{memberName}` on Type `{originalType}` should have been kept");
+
+ assertExpectedAttribute (linkedMethod, expectedAttributeTypeName);
+ return;
+ }
+
+ Assert.Fail ($"Invalid test assertion. No member named `{memberName}` exists on the original type `{originalType}`");
+ }
+
+ void VerifyCustomAttributeKept (ICustomAttributeProvider provider, string expectedAttributeTypeName)
+ {
+ var match = provider.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.FullName == expectedAttributeTypeName);
+ if (match == null)
+ Assert.Fail ($"Expected `{provider}` to have an attribute of type `{expectedAttributeTypeName}`");
+ }
+
+ void VerifyCustomAttributeRemoved (ICustomAttributeProvider provider, string expectedAttributeTypeName)
+ {
+ var match = provider.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.FullName == expectedAttributeTypeName);
+ if (match != null)
+ Assert.Fail ($"Expected `{provider}` to no longer have an attribute of type `{expectedAttributeTypeName}`");
+ }
+
+ void VerifyRemovedInterfaceOnTypeInAssembly (CustomAttribute inAssemblyAttribute, TypeDefinition linkedType)
+ {
+ var originalType = GetOriginalTypeFromInAssemblyAttribute (inAssemblyAttribute);
+
+ var interfaceAssemblyName = inAssemblyAttribute.ConstructorArguments [2].Value.ToString ();
+ var interfaceType = inAssemblyAttribute.ConstructorArguments [3].Value;
+
+ var originalInterface = GetOriginalTypeFromInAssemblyAttribute (interfaceAssemblyName, interfaceType);
+ if (!originalType.HasInterfaces)
+ Assert.Fail ("Invalid assertion. Original type does not have any interfaces");
+
+ var originalInterfaceImpl = GetMatchingInterfaceImplementationOnType (originalType, originalInterface.FullName);
+ if (originalInterfaceImpl == null)
+ Assert.Fail ($"Invalid assertion. Original type never had an interface of type `{originalInterface}`");
+
+ var linkedInterfaceImpl = GetMatchingInterfaceImplementationOnType (linkedType, originalInterface.FullName);
+ if (linkedInterfaceImpl != null)
+ Assert.Fail ($"Expected `{linkedType}` to no longer have an interface of type {originalInterface.FullName}");
+ }
+
+ void VerifyKeptInterfaceOnTypeInAssembly (CustomAttribute inAssemblyAttribute, TypeDefinition linkedType)
+ {
+ var originalType = GetOriginalTypeFromInAssemblyAttribute (inAssemblyAttribute);
+
+ var interfaceAssemblyName = inAssemblyAttribute.ConstructorArguments [2].Value.ToString ();
+ var interfaceType = inAssemblyAttribute.ConstructorArguments [3].Value;
+
+ var originalInterface = GetOriginalTypeFromInAssemblyAttribute (interfaceAssemblyName, interfaceType);
+ if (!originalType.HasInterfaces)
+ Assert.Fail ("Invalid assertion. Original type does not have any interfaces");
+
+ var originalInterfaceImpl = GetMatchingInterfaceImplementationOnType (originalType, originalInterface.FullName);
+ if (originalInterfaceImpl == null)
+ Assert.Fail ($"Invalid assertion. Original type never had an interface of type `{originalInterface}`");
+
+ var linkedInterfaceImpl = GetMatchingInterfaceImplementationOnType (linkedType, originalInterface.FullName);
+ if (linkedInterfaceImpl == null)
+ Assert.Fail ($"Expected `{linkedType}` to have interface of type {originalInterface.FullName}");
+ }
+
+ void VerifyKeptBaseOnTypeInAssembly (CustomAttribute inAssemblyAttribute, TypeDefinition linkedType)
+ {
+ var originalType = GetOriginalTypeFromInAssemblyAttribute (inAssemblyAttribute);
+
+ var baseAssemblyName = inAssemblyAttribute.ConstructorArguments [2].Value.ToString ();
+ var baseType = inAssemblyAttribute.ConstructorArguments [3].Value;
+
+ var originalBase = GetOriginalTypeFromInAssemblyAttribute (baseAssemblyName, baseType);
+ if (originalType.BaseType.Resolve () != originalBase)
+ Assert.Fail ("Invalid assertion. Original type's base does not match the expected base");
+
+ Assert.That (originalBase.FullName, Is.EqualTo (linkedType.BaseType.FullName),
+ $"Incorrect base on `{linkedType.FullName}`. Expected `{originalBase.FullName}` but was `{linkedType.BaseType.FullName}`");
+ }
+
+ protected static InterfaceImplementation GetMatchingInterfaceImplementationOnType (TypeDefinition type, string expectedInterfaceTypeName)
+ {
+ return type.Interfaces.FirstOrDefault (impl =>
+ {
+ var resolvedImpl = impl.InterfaceType.Resolve ();
+
+ if (resolvedImpl == null)
+ Assert.Fail ($"Failed to resolve interface : `{impl.InterfaceType}` on `{type}`");
+
+ return resolvedImpl.FullName == expectedInterfaceTypeName;
+ });
+ }
+
+ void VerifyRemovedMemberInAssembly (CustomAttribute inAssemblyAttribute, TypeDefinition linkedType)
+ {
+ var originalType = GetOriginalTypeFromInAssemblyAttribute (inAssemblyAttribute);
+ foreach (var memberNameAttr in (CustomAttributeArgument[]) inAssemblyAttribute.ConstructorArguments [2].Value) {
+ string memberName = (string) memberNameAttr.Value;
+
+ // We will find the matching type from the original assembly first that way we can confirm
+ // that the name defined in the attribute corresponds to a member that actually existed
+ var originalFieldMember = originalType.Fields.FirstOrDefault (m => m.Name == memberName);
+ if (originalFieldMember != null) {
+ var linkedField = linkedType.Fields.FirstOrDefault (m => m.Name == memberName);
+ if (linkedField != null)
+ Assert.Fail ($"Field `{memberName}` on Type `{originalType}` should have been removed");
+
+ continue;
+ }
+
+ var originalPropertyMember = originalType.Properties.FirstOrDefault (m => m.Name == memberName);
+ if (originalPropertyMember != null) {
+ var linkedProperty = linkedType.Properties.FirstOrDefault (m => m.Name == memberName);
+ if (linkedProperty != null)
+ Assert.Fail ($"Property `{memberName}` on Type `{originalType}` should have been removed");
+
+ continue;
+ }
+
+ var originalMethodMember = originalType.Methods.FirstOrDefault (m => m.GetSignature () == memberName);
+ if (originalMethodMember != null) {
+ var linkedMethod = linkedType.Methods.FirstOrDefault (m => m.GetSignature () == memberName);
+ if (linkedMethod != null)
+ Assert.Fail ($"Method `{memberName}` on Type `{originalType}` should have been removed");
+
+ continue;
+ }
+
+ Assert.Fail ($"Invalid test assertion. No member named `{memberName}` exists on the original type `{originalType}`");
+ }
+ }
+
+ void VerifyKeptMemberInAssembly (CustomAttribute inAssemblyAttribute, TypeDefinition linkedType)
+ {
+ var originalType = GetOriginalTypeFromInAssemblyAttribute (inAssemblyAttribute);
+ foreach (var memberNameAttr in (CustomAttributeArgument[]) inAssemblyAttribute.ConstructorArguments [2].Value) {
+ string memberName = (string) memberNameAttr.Value;
+
+ // We will find the matching type from the original assembly first that way we can confirm
+ // that the name defined in the attribute corresponds to a member that actually existed
+
+ if (TryVerifyKeptMemberInAssemblyAsField (memberName, originalType, linkedType))
+ continue;
+
+ if (TryVerifyKeptMemberInAssemblyAsProperty (memberName, originalType, linkedType))
+ continue;
+
+ if (TryVerifyKeptMemberInAssemblyAsMethod (memberName, originalType, linkedType))
+ continue;
+
+ Assert.Fail ($"Invalid test assertion. No member named `{memberName}` exists on the original type `{originalType}`");
+ }
+ }
+
+ protected virtual bool TryVerifyKeptMemberInAssemblyAsField (string memberName, TypeDefinition originalType, TypeDefinition linkedType)
+ {
+ var originalFieldMember = originalType.Fields.FirstOrDefault (m => m.Name == memberName);
+ if (originalFieldMember != null) {
+ var linkedField = linkedType.Fields.FirstOrDefault (m => m.Name == memberName);
+ if (linkedField == null)
+ Assert.Fail ($"Field `{memberName}` on Type `{originalType}` should have been kept");
+
+ return true;
+ }
+
+ return false;
+ }
+
+ protected virtual bool TryVerifyKeptMemberInAssemblyAsProperty (string memberName, TypeDefinition originalType, TypeDefinition linkedType)
+ {
+ var originalPropertyMember = originalType.Properties.FirstOrDefault (m => m.Name == memberName);
+ if (originalPropertyMember != null) {
+ var linkedProperty = linkedType.Properties.FirstOrDefault (m => m.Name == memberName);
+ if (linkedProperty == null)
+ Assert.Fail ($"Property `{memberName}` on Type `{originalType}` should have been kept");
+
+ return true;
+ }
+
+ return false;
+ }
+
+ protected virtual bool TryVerifyKeptMemberInAssemblyAsMethod (string memberName, TypeDefinition originalType, TypeDefinition linkedType)
+ {
+ var originalMethodMember = originalType.Methods.FirstOrDefault (m => m.GetSignature() == memberName);
+ if (originalMethodMember != null) {
+ var linkedMethod = linkedType.Methods.FirstOrDefault (m => m.GetSignature() == memberName);
+ if (linkedMethod == null)
+ Assert.Fail ($"Method `{memberName}` on Type `{originalType}` should have been kept");
+
+ return true;
+ }
+
+ return false;
+ }
+
+ void VerifyKeptReferencesInAssembly (CustomAttribute inAssemblyAttribute)
+ {
+ var assembly = ResolveLinkedAssembly (inAssemblyAttribute.ConstructorArguments [0].Value.ToString ());
+ var expectedReferenceNames = ((CustomAttributeArgument []) inAssemblyAttribute.ConstructorArguments [1].Value).Select (attr => (string) attr.Value);
+ Assert.That (assembly.MainModule.AssemblyReferences.Select (asm => asm.Name), Is.EquivalentTo (expectedReferenceNames));
+ }
+
+ void VerifyKeptResourceInAssembly (CustomAttribute inAssemblyAttribute)
+ {
+ var assembly = ResolveLinkedAssembly (inAssemblyAttribute.ConstructorArguments [0].Value.ToString ());
+ var resourceName = inAssemblyAttribute.ConstructorArguments [1].Value.ToString ();
+
+ Assert.That (assembly.MainModule.Resources.Select (r => r.Name), Has.Member (resourceName));
+ }
+
+ void VerifyRemovedResourceInAssembly (CustomAttribute inAssemblyAttribute)
+ {
+ var assembly = ResolveLinkedAssembly (inAssemblyAttribute.ConstructorArguments [0].Value.ToString ());
+ var resourceName = inAssemblyAttribute.ConstructorArguments [1].Value.ToString ();
+
+ Assert.That (assembly.MainModule.Resources.Select (r => r.Name), Has.No.Member (resourceName));
+ }
+
+ void VerifyKeptAllTypesAndMembersInAssembly (AssemblyDefinition linked)
+ {
+ var original = ResolveOriginalsAssembly (linked.MainModule.Assembly.Name.Name);
+
+ if (original == null)
+ Assert.Fail ($"Failed to resolve original assembly {linked.MainModule.Assembly.Name.Name}");
+
+ var originalTypes = original.AllDefinedTypes ().ToDictionary (t => t.FullName);
+ var linkedTypes = linked.AllDefinedTypes ().ToDictionary (t => t.FullName);
+
+ var missingInLinked = originalTypes.Keys.Except (linkedTypes.Keys);
+
+ Assert.That (missingInLinked, Is.Empty, $"Expected all types to exist in the linked assembly, but one or more were missing");
+
+ foreach (var originalKvp in originalTypes) {
+ var linkedType = linkedTypes [originalKvp.Key];
+
+ var originalMembers = originalKvp.Value.AllMembers ().Select (m => m.FullName);
+ var linkedMembers = linkedType.AllMembers ().Select (m => m.FullName);
+
+ var missingMembersInLinked = originalMembers.Except (linkedMembers);
+
+ Assert.That (missingMembersInLinked, Is.Empty, $"Expected all members of `{originalKvp.Key}`to exist in the linked assembly, but one or more were missing");
+ }
+ }
+
+ protected TypeDefinition GetOriginalTypeFromInAssemblyAttribute (CustomAttribute inAssemblyAttribute)
+ {
+ return GetOriginalTypeFromInAssemblyAttribute (inAssemblyAttribute.ConstructorArguments [0].Value.ToString (), inAssemblyAttribute.ConstructorArguments [1].Value);
+ }
+
+ protected TypeDefinition GetOriginalTypeFromInAssemblyAttribute (string assemblyName, object typeOrTypeName)
+ {
+ var attributeValueAsTypeReference = typeOrTypeName as TypeReference;
+ if (attributeValueAsTypeReference != null)
+ return attributeValueAsTypeReference.Resolve ();
+
+ var assembly = ResolveOriginalsAssembly (assemblyName);
+
+ var expectedTypeName = typeOrTypeName.ToString ();
+ var originalType = assembly.MainModule.GetType (expectedTypeName);
+ if (originalType == null)
+ Assert.Fail ($"Invalid test assertion. Unable to locate the original type `{expectedTypeName}.`");
+ return originalType;
+ }
+
+ Dictionary<string, List<CustomAttribute>> BuildOtherAssemblyCheckTable (AssemblyDefinition original)
+ {
+ var checks = new Dictionary<string, List<CustomAttribute>> ();
+
+ foreach (var typeWithRemoveInAssembly in original.AllDefinedTypes ()) {
+ foreach (var attr in typeWithRemoveInAssembly.CustomAttributes.Where (IsTypeInOtherAssemblyAssertion)) {
+ var assemblyName = (string) attr.ConstructorArguments [0].Value;
+ List<CustomAttribute> checksForAssembly;
+ if (!checks.TryGetValue (assemblyName, out checksForAssembly))
+ checks [assemblyName] = checksForAssembly = new List<CustomAttribute> ();
+
+ checksForAssembly.Add (attr);
+ }
+ }
+
+ return checks;
+ }
+
+ protected virtual void UnhandledOtherAssemblyAssertion (string expectedTypeName, CustomAttribute checkAttrInAssembly, TypeDefinition linkedType)
+ {
+ throw new NotImplementedException ($"Type {expectedTypeName}, has an unknown other assembly attribute of type {checkAttrInAssembly.AttributeType}");
+ }
+
+ bool IsTypeInOtherAssemblyAssertion (CustomAttribute attr)
+ {
+ return attr.AttributeType.Resolve ().DerivesFrom (nameof (BaseInAssemblyAttribute));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs b/test/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs
new file mode 100644
index 000000000..a8f0525cd
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs
@@ -0,0 +1,15 @@
+using System;
+using Mono.Linker.Tests.Extensions;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class SetupCompileInfo {
+ public string OutputName;
+ public NPath[] SourceFiles;
+ public string[] Defines;
+ public string[] References;
+ public NPath[] Resources;
+ public string AdditionalArguments;
+ public string CompilerToUse;
+ public bool AddAsReference;
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/SourceAndDestinationPair.cs b/test/Mono.Linker.Tests/TestCasesRunner/SourceAndDestinationPair.cs
new file mode 100644
index 000000000..762887a13
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/SourceAndDestinationPair.cs
@@ -0,0 +1,9 @@
+using System;
+using Mono.Linker.Tests.Extensions;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class SourceAndDestinationPair {
+ public NPath Source;
+ public string DestinationFileName;
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseAssemblyResolver.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseAssemblyResolver.cs
new file mode 100644
index 000000000..0c3c82583
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseAssemblyResolver.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using Mono.Cecil;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class TestCaseAssemblyResolver : DefaultAssemblyResolver {
+ readonly HashSet<IDisposable> itemsToDispose;
+
+ public TestCaseAssemblyResolver ()
+ {
+ itemsToDispose = new HashSet<IDisposable> ();
+ }
+
+ public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters)
+ {
+ var assembly = base.Resolve (name, parameters);
+
+ if (assembly == null)
+ return null;
+
+ // Don't do any caching because the reader parameters could be different each time
+ // but we still want to track items that need to be disposed for easy clean up
+ itemsToDispose.Add (assembly);
+
+ if (assembly.MainModule.SymbolReader != null)
+ itemsToDispose.Add (assembly.MainModule.SymbolReader);
+ return assembly;
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ foreach (var item in itemsToDispose)
+ item.Dispose ();
+
+ base.Dispose (disposing);
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCollector.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCollector.cs
new file mode 100644
index 000000000..5c4f4dbc9
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCollector.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Linker.Tests.TestCases;
+using Mono.Linker.Tests.Extensions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class TestCaseCollector {
+ private readonly NPath _rootDirectory;
+ private readonly NPath _testCaseAssemblyPath;
+
+ public TestCaseCollector (string rootDirectory, string testCaseAssemblyPath)
+ : this (rootDirectory.ToNPath (), testCaseAssemblyPath.ToNPath ())
+ {
+ }
+
+ public TestCaseCollector (NPath rootDirectory, NPath testCaseAssemblyPath)
+ {
+ _rootDirectory = rootDirectory;
+ _testCaseAssemblyPath = testCaseAssemblyPath;
+ }
+
+ public IEnumerable<TestCase> Collect ()
+ {
+ return Collect (AllSourceFiles ());
+ }
+
+ public TestCase Collect (NPath sourceFile)
+ {
+ return Collect (new [] { sourceFile }).First ();
+ }
+
+ public IEnumerable<TestCase> Collect (IEnumerable<NPath> sourceFiles)
+ {
+ _rootDirectory.DirectoryMustExist ();
+ _testCaseAssemblyPath.FileMustExist ();
+
+ using (var caseAssemblyDefinition = AssemblyDefinition.ReadAssembly (_testCaseAssemblyPath.ToString ())) {
+ foreach (var file in sourceFiles) {
+ TestCase testCase;
+ if (CreateCase (caseAssemblyDefinition, file, out testCase))
+ yield return testCase;
+ }
+ }
+ }
+
+ public IEnumerable<NPath> AllSourceFiles ()
+ {
+ _rootDirectory.DirectoryMustExist ();
+
+ foreach (var file in _rootDirectory.Files ("*.cs")) {
+ yield return file;
+ }
+
+ foreach (var subDir in _rootDirectory.Directories ()) {
+ if (subDir.FileName == "bin" || subDir.FileName == "obj" || subDir.FileName == "Properties")
+ continue;
+
+ foreach (var file in subDir.Files ("*.cs", true)) {
+
+ var relativeParents = file.RelativeTo(_rootDirectory);
+ // Magic : Anything in a directory named Dependencies is assumed to be a dependency to a test case
+ // and never a test itself
+ // This makes life a little easier when writing these supporting files as it removes some constraints you would previously have
+ // had to follow such as ensuring a class exists that matches the file name and putting [NotATestCase] on that class
+ if (relativeParents.RecursiveParents.Any(p => p.Elements.Any() && p.FileName == "Dependencies"))
+ continue;
+
+ // Magic: Anything in a directory named Individual is expected to be ran by it's own [Test] rather than as part of [TestCaseSource]
+ if (relativeParents.RecursiveParents.Any(p => p.Elements.Any() && p.FileName == "Individual"))
+ continue;
+
+ yield return file;
+ }
+ }
+ }
+
+ public TestCase CreateIndividualCase (Type testCaseType)
+ {
+ _rootDirectory.DirectoryMustExist ();
+ _testCaseAssemblyPath.FileMustExist ();
+
+ var pathRelativeToAssembly = $"{testCaseType.FullName.Substring (testCaseType.Module.Name.Length - 3).Replace ('.', '/')}.cs";
+ var fullSourcePath = _rootDirectory.Combine (pathRelativeToAssembly).FileMustExist ();
+
+ using (var caseAssemblyDefinition = AssemblyDefinition.ReadAssembly (_testCaseAssemblyPath.ToString ()))
+ {
+ TestCase testCase;
+ if (!CreateCase (caseAssemblyDefinition, fullSourcePath, out testCase))
+ throw new ArgumentException ($"Could not create a test case for `{testCaseType}`. Ensure the namespace matches it's location on disk");
+
+ return testCase;
+ }
+ }
+
+ private bool CreateCase (AssemblyDefinition caseAssemblyDefinition, NPath sourceFile, out TestCase testCase)
+ {
+ var potentialCase = new TestCase (sourceFile, _rootDirectory, _testCaseAssemblyPath);
+
+ var typeDefinition = FindTypeDefinition (caseAssemblyDefinition, potentialCase);
+
+ testCase = null;
+
+ if (typeDefinition == null) {
+ Console.WriteLine ($"Could not find the matching type for test case {sourceFile}. Ensure the file name and class name match");
+ return false;
+ }
+
+ if (typeDefinition.HasAttribute (nameof (NotATestCaseAttribute))) {
+ return false;
+ }
+
+ // Verify the class as a static main method
+ var mainMethod = typeDefinition.Methods.FirstOrDefault (m => m.Name == "Main");
+
+ if (mainMethod == null) {
+ Console.WriteLine ($"{typeDefinition} in {sourceFile} is missing a Main() method");
+ return false;
+ }
+
+ if (!mainMethod.IsStatic) {
+ Console.WriteLine ($"The Main() method for {typeDefinition} in {sourceFile} should be static");
+ return false;
+ }
+
+ testCase = potentialCase;
+ return true;
+ }
+
+ private static TypeDefinition FindTypeDefinition (AssemblyDefinition caseAssemblyDefinition, TestCase testCase)
+ {
+ var typeDefinition = caseAssemblyDefinition.MainModule.GetType (testCase.ReconstructedFullTypeName);
+
+ // For all of the Test Cases, the full type name we constructed from the directory structure will be correct and we can successfully find
+ // the type from GetType.
+ if (typeDefinition != null)
+ return typeDefinition;
+
+ // However, some of types are supporting types rather than test cases. and may not follow the standardized naming scheme of the test cases
+ // We still need to be able to locate these type defs so that we can parse some of the metadata on them.
+ // One example, Unity run's into this with it's tests that require a type UnityEngine.MonoBehaviours to exist. This tpe is defined in it's own
+ // file and it cannot follow our standardized naming directory & namespace naming scheme since the namespace must be UnityEngine
+ foreach (var type in caseAssemblyDefinition.MainModule.Types) {
+ // Let's assume we should never have to search for a test case that has no namespace. If we don't find the type from GetType, then o well, that's not a test case.
+ if (string.IsNullOrEmpty (type.Namespace))
+ continue;
+
+ if (type.Name == testCase.Name) {
+ // This isn't foolproof, but let's do a little extra vetting to make sure the type we found corresponds to the source file we are
+ // processing.
+ if (!testCase.SourceFile.ReadAllText ().Contains ($"namespace {type.Namespace}"))
+ continue;
+
+ return type;
+ }
+ }
+
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs
new file mode 100644
index 000000000..afa1eb6a3
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs
@@ -0,0 +1,357 @@
+using System;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Mono.Linker.Tests.Extensions;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class TestCaseCompiler {
+ static string _cachedWindowsCscPath = null;
+ protected readonly TestCaseMetadaProvider _metadataProvider;
+ protected readonly TestCaseSandbox _sandbox;
+ protected readonly ILCompiler _ilCompiler;
+
+ public TestCaseCompiler (TestCaseSandbox sandbox, TestCaseMetadaProvider metadataProvider)
+ : this(sandbox, metadataProvider, new ILCompiler ())
+ {
+ }
+
+ public TestCaseCompiler (TestCaseSandbox sandbox, TestCaseMetadaProvider metadataProvider, ILCompiler ilCompiler)
+ {
+ _ilCompiler = ilCompiler;
+ _sandbox = sandbox;
+ _metadataProvider = metadataProvider;
+ }
+
+ public NPath CompileTestIn (NPath outputDirectory, string outputName, IEnumerable<string> sourceFiles, string[] commonReferences, string[] mainAssemblyReferences, IEnumerable<string> defines, NPath[] resources, string[] additionalArguments)
+ {
+ var originalCommonReferences = commonReferences.Select (r => r.ToNPath ()).ToArray ();
+ var originalDefines = defines?.ToArray () ?? new string [0];
+
+ Prepare (outputDirectory);
+
+ var compiledReferences = CompileBeforeTestCaseAssemblies (outputDirectory, originalCommonReferences, originalDefines).ToArray ();
+ var allTestCaseReferences = originalCommonReferences
+ .Concat (compiledReferences)
+ .Concat (mainAssemblyReferences.Select (r => r.ToNPath ()))
+ .ToArray ();
+
+ var options = CreateOptionsForTestCase (
+ outputDirectory.Combine (outputName),
+ sourceFiles.Select (s => s.ToNPath ()).ToArray (),
+ allTestCaseReferences,
+ originalDefines,
+ resources,
+ additionalArguments);
+ var testAssembly = CompileAssembly (options);
+
+
+ // The compile after step is used by tests to mess around with the input to the linker. Generally speaking, it doesn't seem like we would ever want to mess with the
+ // expectations assemblies because this would undermine our ability to inspect them for expected results during ResultChecking. The UnityLinker UnresolvedHandling tests depend on this
+ // behavior of skipping the after test compile
+ if (outputDirectory != _sandbox.ExpectationsDirectory)
+ CompileAfterTestCaseAssemblies (outputDirectory, originalCommonReferences, originalDefines);
+
+ return testAssembly;
+ }
+
+ protected virtual void Prepare (NPath outputDirectory)
+ {
+ }
+
+ protected virtual CompilerOptions CreateOptionsForTestCase (NPath outputPath, NPath[] sourceFiles, NPath[] references, string[] defines, NPath[] resources, string[] additionalArguments)
+ {
+ return new CompilerOptions
+ {
+ OutputPath = outputPath,
+ SourceFiles = sourceFiles,
+ References = references,
+ Defines = defines.Concat (_metadataProvider.GetDefines ()).ToArray (),
+ Resources = resources,
+ AdditionalArguments = additionalArguments,
+ CompilerToUse = _metadataProvider.GetCSharpCompilerToUse ()
+ };
+ }
+
+ protected virtual CompilerOptions CreateOptionsForSupportingAssembly (SetupCompileInfo setupCompileInfo, NPath outputDirectory, NPath[] sourceFiles, NPath[] references, string[] defines, NPath[] resources)
+ {
+ var allDefines = defines.Concat (setupCompileInfo.Defines ?? new string [0]).ToArray ();
+ var allReferences = references.Concat (setupCompileInfo.References?.Select (p => MakeSupportingAssemblyReferencePathAbsolute (outputDirectory, p)) ?? new NPath [0]).ToArray ();
+ string[] additionalArguments = string.IsNullOrEmpty (setupCompileInfo.AdditionalArguments) ? null : new[] { setupCompileInfo.AdditionalArguments };
+ return new CompilerOptions
+ {
+ OutputPath = outputDirectory.Combine (setupCompileInfo.OutputName),
+ SourceFiles = sourceFiles,
+ References = allReferences,
+ Defines = allDefines,
+ Resources = resources,
+ AdditionalArguments = additionalArguments,
+ CompilerToUse = setupCompileInfo.CompilerToUse?.ToLower ()
+ };
+ }
+
+ private IEnumerable<NPath> CompileBeforeTestCaseAssemblies (NPath outputDirectory, NPath[] references, string[] defines)
+ {
+ foreach (var setupCompileInfo in _metadataProvider.GetSetupCompileAssembliesBefore ())
+ {
+ var options = CreateOptionsForSupportingAssembly (
+ setupCompileInfo,
+ outputDirectory,
+ CollectSetupBeforeSourcesFiles (setupCompileInfo),
+ references,
+ defines,
+ CollectSetupBeforeResourcesFiles (setupCompileInfo));
+ var output = CompileAssembly (options);
+ if (setupCompileInfo.AddAsReference)
+ yield return output;
+ }
+ }
+
+ private void CompileAfterTestCaseAssemblies (NPath outputDirectory, NPath[] references, string[] defines)
+ {
+ foreach (var setupCompileInfo in _metadataProvider.GetSetupCompileAssembliesAfter ())
+ {
+ var options = CreateOptionsForSupportingAssembly (
+ setupCompileInfo,
+ outputDirectory,
+ CollectSetupAfterSourcesFiles (setupCompileInfo),
+ references,
+ defines,
+ CollectSetupAfterResourcesFiles (setupCompileInfo));
+ CompileAssembly (options);
+ }
+ }
+
+ private NPath[] CollectSetupBeforeSourcesFiles (SetupCompileInfo info)
+ {
+ return CollectSourceFilesFrom (_sandbox.BeforeReferenceSourceDirectoryFor (info.OutputName));
+ }
+
+ private NPath[] CollectSetupAfterSourcesFiles (SetupCompileInfo info)
+ {
+ return CollectSourceFilesFrom (_sandbox.AfterReferenceSourceDirectoryFor (info.OutputName));
+ }
+
+ private NPath[] CollectSetupBeforeResourcesFiles (SetupCompileInfo info)
+ {
+ return _sandbox.BeforeReferenceResourceDirectoryFor (info.OutputName).Files ().ToArray ();
+ }
+
+ private NPath[] CollectSetupAfterResourcesFiles (SetupCompileInfo info)
+ {
+ return _sandbox.AfterReferenceResourceDirectoryFor (info.OutputName).Files ().ToArray ();
+ }
+
+ private static NPath[] CollectSourceFilesFrom (NPath directory)
+ {
+ var sourceFiles = directory.Files ("*.cs").ToArray ();
+ if (sourceFiles.Length > 0)
+ return sourceFiles;
+
+ sourceFiles = directory.Files ("*.il").ToArray ();
+ if (sourceFiles.Length > 0)
+ return sourceFiles;
+
+ throw new FileNotFoundException ($"Didn't find any sources files in {directory}");
+ }
+
+ protected static NPath MakeSupportingAssemblyReferencePathAbsolute (NPath outputDirectory, string referenceFileName)
+ {
+ // Not a good idea to use a full path in a test, but maybe someone is trying to quickly test something locally
+ if (Path.IsPathRooted (referenceFileName))
+ return referenceFileName.ToNPath ();
+
+ var possiblePath = outputDirectory.Combine (referenceFileName);
+ if (possiblePath.FileExists ())
+ return possiblePath;
+
+ return referenceFileName.ToNPath();
+ }
+
+ protected NPath CompileAssembly (CompilerOptions options)
+ {
+ if (options.SourceFiles.Any (path => path.ExtensionWithDot == ".cs"))
+ return CompileCSharpAssembly (options);
+
+ if (options.SourceFiles.Any (path => path.ExtensionWithDot == ".il"))
+ return CompileIlAssembly (options);
+
+ throw new NotSupportedException ($"Unable to compile sources files with extension `{options.SourceFiles.First ().ExtensionWithDot}`");
+ }
+
+ protected virtual NPath CompileCSharpAssemblyWithDefaultCompiler (CompilerOptions options)
+ {
+ var compilerOptions = CreateCodeDomCompilerOptions (options);
+ var provider = CodeDomProvider.CreateProvider ("C#");
+ var result = provider.CompileAssemblyFromFile (compilerOptions, options.SourceFiles.Select (p => p.ToString ()).ToArray ());
+ if (!result.Errors.HasErrors)
+ return compilerOptions.OutputAssembly.ToNPath ();
+
+ var errors = new StringBuilder ();
+ foreach (var error in result.Errors)
+ errors.AppendLine (error.ToString ());
+ throw new Exception ("Compilation errors: " + errors);
+ }
+
+ protected virtual NPath CompileCSharpAssemblyWithCsc (CompilerOptions options)
+ {
+ return CompileCSharpAssemblyWithExternalCompiler (LocateCscExecutable (), options);
+ }
+
+ protected virtual NPath CompileCSharpAssemblyWithMsc(CompilerOptions options)
+ {
+ if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+ CompileCSharpAssemblyWithExternalCompiler (LocateMcsExecutable (), options);
+
+ return CompileCSharpAssemblyWithDefaultCompiler (options);
+ }
+
+ protected NPath CompileCSharpAssemblyWithExternalCompiler (string executable, CompilerOptions options)
+ {
+ var capturedOutput = new List<string> ();
+ var process = new Process ();
+ process.StartInfo.FileName = executable;
+ process.StartInfo.Arguments = OptionsToCompilerCommandLineArguments (options);
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.CreateNoWindow = true;
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ process.StartInfo.RedirectStandardOutput = true;
+ process.OutputDataReceived += (sender, args) => capturedOutput.Add (args.Data);
+ process.Start ();
+ process.BeginOutputReadLine ();
+ process.WaitForExit ();
+
+ if (process.ExitCode != 0)
+ Assert.Fail ($"Failed to compile assembly with csc: {options.OutputPath}\n{capturedOutput.Aggregate ((buff, s) => buff + Environment.NewLine + s)}");
+
+ return options.OutputPath;
+ }
+
+ static string LocateCscExecutable ()
+ {
+ if (Environment.OSVersion.Platform != PlatformID.Win32NT)
+ return "csc";
+
+ if (_cachedWindowsCscPath != null)
+ return _cachedWindowsCscPath;
+
+ var capturedOutput = new List<string> ();
+ var process = new Process ();
+
+ var vswherePath = Environment.ExpandEnvironmentVariables ("%ProgramFiles(x86)%\\Microsoft Visual Studio\\Installer\\vswhere.exe");
+ if (!File.Exists (vswherePath))
+ Assert.Fail ($"Unable to locate csc.exe on windows because vshwere.exe was not found at {vswherePath}");
+
+ process.StartInfo.FileName = vswherePath;
+ process.StartInfo.Arguments = "-latest -products * -requires Microsoft.Component.MSBuild -property installationPath";
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.CreateNoWindow = true;
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ process.StartInfo.RedirectStandardOutput = true;
+ process.OutputDataReceived += (sender, args) => capturedOutput.Add (args.Data);
+ process.Start ();
+ process.BeginOutputReadLine ();
+ process.WaitForExit ();
+
+ if (process.ExitCode != 0)
+ Assert.Fail ($"vswhere.exe failed with :\n{capturedOutput.Aggregate ((buff, s) => buff + Environment.NewLine + s)}");
+
+ if (capturedOutput.Count == 0 || string.IsNullOrEmpty (capturedOutput [0]))
+ Assert.Fail ("vswhere.exe was unable to locate an install directory");
+
+ var installPath = capturedOutput [0].Trim ().ToNPath ();
+
+ if (!installPath.Exists ())
+ Assert.Fail ($"No install found at {installPath}");
+
+ // Do a search for the roslyn directory for a little bit of furture proofing since it normally lives under
+ // a versioned msbuild directory
+ foreach (var roslynDirectory in installPath.Directories ("Roslyn", true)) {
+ var possibleCscPath = roslynDirectory.Combine ("csc.exe");
+ if (possibleCscPath.Exists ()) {
+ _cachedWindowsCscPath = possibleCscPath.ToString ();
+ return _cachedWindowsCscPath;
+ }
+ }
+
+ Assert.Fail ("Unable to locate a roslyn csc.exe");
+ return null;
+ }
+
+ static string LocateMcsExecutable ()
+ {
+ if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+ Assert.Ignore ("We don't have a universal way of locating mcs on Windows");
+
+ return "mcs";
+ }
+
+ protected string OptionsToCompilerCommandLineArguments (CompilerOptions options)
+ {
+ var builder = new StringBuilder ();
+ builder.Append ($"/out:{options.OutputPath}");
+ var target = options.OutputPath.ExtensionWithDot == ".exe" ? "exe" : "library";
+ builder.Append ($" /target:{target}");
+ if (options.Defines != null && options.Defines.Length > 0)
+ builder.Append (options.Defines.Aggregate (string.Empty, (buff, arg) => $"{buff} /define:{arg}"));
+
+ builder.Append (options.References.Aggregate (string.Empty, (buff, arg) => $"{buff} /r:{arg}"));
+
+ if (options.Resources != null && options.Resources.Length > 0)
+ builder.Append (options.Resources.Aggregate (string.Empty, (buff, arg) => $"{buff} /res:{arg}"));
+
+ if (options.AdditionalArguments != null && options.AdditionalArguments.Length > 0)
+ builder.Append (options.AdditionalArguments.Aggregate (string.Empty, (buff, arg) => $"{buff} {arg}"));
+
+ builder.Append (options.SourceFiles.Aggregate (string.Empty, (buff, arg) => $"{buff} {arg}"));
+
+ return builder.ToString ();
+ }
+
+ protected NPath CompileCSharpAssembly (CompilerOptions options)
+ {
+ if (string.IsNullOrEmpty (options.CompilerToUse))
+ return CompileCSharpAssemblyWithDefaultCompiler (options);
+
+ if (options.CompilerToUse == "csc")
+ return CompileCSharpAssemblyWithCsc (options);
+
+ if (options.CompilerToUse == "mcs")
+ return CompileCSharpAssemblyWithMsc (options);
+
+ throw new ArgumentException ($"Invalid compiler value `{options.CompilerToUse}`");
+ }
+
+ protected NPath CompileIlAssembly (CompilerOptions options)
+ {
+ return _ilCompiler.Compile (options);
+ }
+
+ private CompilerParameters CreateCodeDomCompilerOptions (CompilerOptions options)
+ {
+ var compilerParameters = new CompilerParameters
+ {
+ OutputAssembly = options.OutputPath.ToString (),
+ GenerateExecutable = options.OutputPath.FileName.EndsWith (".exe")
+ };
+
+ compilerParameters.CompilerOptions = options.Defines?.Aggregate (string.Empty, (buff, arg) => $"{buff} /define:{arg}");
+
+ compilerParameters.ReferencedAssemblies.AddRange (options.References.Select (r => r.ToString ()).ToArray ());
+
+ if (options.Resources != null)
+ compilerParameters.EmbeddedResources.AddRange (options.Resources.Select (r => r.ToString ()).ToArray ());
+
+ if (options.AdditionalArguments != null) {
+ var combinedValues = options.AdditionalArguments.Aggregate (string.Empty, (buff, arg) => $"{buff} {arg}");
+ compilerParameters.CompilerOptions = $"{compilerParameters.CompilerOptions} {combinedValues}";
+ }
+
+ return compilerParameters;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseLinkerOptions.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseLinkerOptions.cs
new file mode 100644
index 000000000..f13b4eafc
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseLinkerOptions.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class TestCaseLinkerOptions
+ {
+ public string CoreAssembliesAction;
+ public string UserAssembliesAction;
+ public List<KeyValuePair<string, string>> AssembliesAction = new List<KeyValuePair<string, string>> ();
+
+ public string Il8n;
+ public bool IncludeBlacklistStep;
+ public string KeepTypeForwarderOnlyAssemblies;
+ public string KeepDebugMembers;
+ public string LinkSymbols;
+ public bool SkipUnresolved;
+ public bool StripResources;
+
+ public List<KeyValuePair<string, string[]>> AdditionalArguments = new List<KeyValuePair<string, string[]>> ();
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs
new file mode 100644
index 000000000..a41b398ff
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadaProvider.cs
@@ -0,0 +1,271 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Mono.Cecil;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+using Mono.Linker.Tests.Extensions;
+using Mono.Linker.Tests.TestCases;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class TestCaseMetadaProvider {
+ protected readonly TestCase _testCase;
+ protected readonly AssemblyDefinition _fullTestCaseAssemblyDefinition;
+ protected readonly TypeDefinition _testCaseTypeDefinition;
+
+ public TestCaseMetadaProvider (TestCase testCase, AssemblyDefinition fullTestCaseAssemblyDefinition)
+ {
+ _testCase = testCase;
+ _fullTestCaseAssemblyDefinition = fullTestCaseAssemblyDefinition;
+ // The test case types are never nested so we don't need to worry about that
+ _testCaseTypeDefinition = fullTestCaseAssemblyDefinition.MainModule.GetType (_testCase.ReconstructedFullTypeName);
+
+ if (_testCaseTypeDefinition == null)
+ throw new InvalidOperationException ($"Could not find the type definition for {_testCase.Name} in {_testCase.SourceFile}");
+ }
+
+ public virtual TestCaseLinkerOptions GetLinkerOptions ()
+ {
+ var tclo = new TestCaseLinkerOptions {
+ Il8n = GetOptionAttributeValue (nameof (Il8nAttribute), "none"),
+ IncludeBlacklistStep = GetOptionAttributeValue (nameof (IncludeBlacklistStepAttribute), false),
+ KeepTypeForwarderOnlyAssemblies = GetOptionAttributeValue (nameof (KeepTypeForwarderOnlyAssembliesAttribute), string.Empty),
+ KeepDebugMembers = GetOptionAttributeValue (nameof (SetupLinkerKeepDebugMembersAttribute), string.Empty),
+ LinkSymbols = GetOptionAttributeValue (nameof (SetupLinkerLinkSymbolsAttribute), string.Empty),
+ CoreAssembliesAction = GetOptionAttributeValue<string> (nameof (SetupLinkerCoreActionAttribute), null),
+ UserAssembliesAction = GetOptionAttributeValue<string> (nameof (SetupLinkerUserActionAttribute), null),
+ SkipUnresolved = GetOptionAttributeValue (nameof (SkipUnresolvedAttribute), false),
+ StripResources = GetOptionAttributeValue (nameof (StripResourcesAttribute), true)
+ };
+
+ foreach (var assemblyAction in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkerActionAttribute)))
+ {
+ var ca = assemblyAction.ConstructorArguments;
+ tclo.AssembliesAction.Add (new KeyValuePair<string, string> ((string)ca [0].Value, (string)ca [1].Value));
+ }
+
+ foreach (var additionalArgumentAttr in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkerArgumentAttribute)))
+ {
+ var ca = additionalArgumentAttr.ConstructorArguments;
+ var values = ((CustomAttributeArgument [])ca [1].Value)?.Select (arg => arg.Value.ToString ()).ToArray ();
+ tclo.AdditionalArguments.Add (new KeyValuePair<string, string []> ((string)ca [0].Value, values));
+ }
+
+ return tclo;
+ }
+
+ public virtual IEnumerable<string> GetCommonReferencedAssemblies (NPath workingDirectory)
+ {
+ yield return workingDirectory.Combine ("Mono.Linker.Tests.Cases.Expectations.dll").ToString ();
+ yield return "mscorlib.dll";
+ }
+
+ public virtual IEnumerable<string> GetReferencedAssemblies (NPath workingDirectory)
+ {
+ foreach (var fileName in GetReferenceValues ()) {
+ if (fileName.StartsWith ("System.", StringComparison.Ordinal) || fileName.StartsWith ("Mono.", StringComparison.Ordinal) || fileName.StartsWith ("Microsoft.", StringComparison.Ordinal))
+ yield return fileName;
+ else
+ // Drop any relative path information. Sandboxing will have taken care of copying the reference to the directory
+ yield return workingDirectory.Combine (Path.GetFileName (fileName));
+ }
+ }
+
+ public virtual IEnumerable<string> GetReferenceDependencies ()
+ {
+ return _testCaseTypeDefinition.CustomAttributes
+ .Where (attr => attr.AttributeType.Name == nameof (ReferenceDependencyAttribute))
+ .Select (attr => (string) attr.ConstructorArguments [0].Value);
+ }
+
+ public virtual IEnumerable<string> GetReferenceValues ()
+ {
+ foreach (var referenceAttr in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (ReferenceAttribute)))
+ yield return (string) referenceAttr.ConstructorArguments.First ().Value;
+ }
+
+ public virtual IEnumerable<SourceAndDestinationPair> GetResources ()
+ {
+ return _testCaseTypeDefinition.CustomAttributes
+ .Where (attr => attr.AttributeType.Name == nameof (SetupCompileResourceAttribute))
+ .Select (GetSourceAndRelativeDestinationValue);
+ }
+
+ public virtual IEnumerable<SourceAndDestinationPair> GetResponseFiles ()
+ {
+ return _testCaseTypeDefinition.CustomAttributes
+ .Where (attr => attr.AttributeType.Name == nameof (SetupLinkerResponseFileAttribute))
+ .Select (GetSourceAndRelativeDestinationValue);
+ }
+
+ public virtual IEnumerable<NPath> GetExtraLinkerSearchDirectories ()
+ {
+ yield break;
+ }
+
+ public virtual bool IsIgnored (out string reason)
+ {
+ var ignoreAttribute = _testCaseTypeDefinition.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == nameof (IgnoreTestCaseAttribute));
+ if (ignoreAttribute != null) {
+ reason = (string)ignoreAttribute.ConstructorArguments.First ().Value;
+ return true;
+ }
+
+ reason = null;
+ return false;
+ }
+
+ public virtual IEnumerable<SourceAndDestinationPair> AdditionalFilesToSandbox ()
+ {
+ return _testCaseTypeDefinition.CustomAttributes
+ .Where (attr => attr.AttributeType.Name == nameof (SandboxDependencyAttribute))
+ .Select (GetSourceAndRelativeDestinationValue);
+ }
+
+ public virtual IEnumerable<SetupCompileInfo> GetSetupCompileAssembliesBefore ()
+ {
+ return _testCaseTypeDefinition.CustomAttributes
+ .Where (attr => attr.AttributeType.Name == nameof (SetupCompileBeforeAttribute))
+ .Select (CreateSetupCompileAssemblyInfo);
+ }
+
+ public virtual IEnumerable<SetupCompileInfo> GetSetupCompileAssembliesAfter ()
+ {
+ return _testCaseTypeDefinition.CustomAttributes
+ .Where (attr => attr.AttributeType.Name == nameof (SetupCompileAfterAttribute))
+ .Select (CreateSetupCompileAssemblyInfo);
+ }
+
+ public virtual IEnumerable<string> GetDefines ()
+ {
+ // There are a few tests related to native pdbs where the assertions are different between windows and non-windows
+ // To enable test cases to define different expected behavior we set this special define
+ if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+ yield return "WIN32";
+
+ foreach (var attr in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (DefineAttribute)))
+ yield return (string) attr.ConstructorArguments.First ().Value;
+ }
+
+ public virtual bool LinkPublicAndFamily()
+ {
+ return _testCaseTypeDefinition.CustomAttributes
+ .FirstOrDefault (attr => attr.AttributeType.Name == nameof (SetupLinkerLinkPublicAndFamilyAttribute)) != null;
+ }
+
+ public virtual string GetAssemblyName ()
+ {
+ var asLibraryAttribute = _testCaseTypeDefinition.CustomAttributes
+ .FirstOrDefault (attr => attr.AttributeType.Name == nameof (SetupCompileAsLibraryAttribute));
+ var defaultName = asLibraryAttribute == null ? "test.exe" : "test.dll";
+ return GetOptionAttributeValue (nameof (SetupCompileAssemblyNameAttribute), defaultName);
+ }
+
+ public virtual string GetCSharpCompilerToUse ()
+ {
+ return GetOptionAttributeValue (nameof (SetupCSharpCompilerToUseAttribute), string.Empty).ToLower ();
+ }
+
+ public virtual IEnumerable<string> GetSetupCompilerArguments ()
+ {
+ return _testCaseTypeDefinition.CustomAttributes
+ .Where (attr => attr.AttributeType.Name == nameof (SetupCompileArgumentAttribute))
+ .Select (attr => (string) attr.ConstructorArguments.First ().Value);
+ }
+
+ T GetOptionAttributeValue<T> (string attributeName, T defaultValue)
+ {
+ var attribute = _testCaseTypeDefinition.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == attributeName);
+ if (attribute != null)
+ return (T) attribute.ConstructorArguments.First ().Value;
+
+ return defaultValue;
+ }
+
+ SourceAndDestinationPair GetSourceAndRelativeDestinationValue (CustomAttribute attribute)
+ {
+ var fullSource = SourceFileForAttributeArgumentValue (attribute.ConstructorArguments.First ().Value);
+ var destinationFileName = (string) attribute.ConstructorArguments [1].Value;
+ return new SourceAndDestinationPair
+ {
+ Source = fullSource,
+ DestinationFileName = string.IsNullOrEmpty (destinationFileName) ? fullSource.FileName : destinationFileName
+ };
+ }
+
+ private SetupCompileInfo CreateSetupCompileAssemblyInfo (CustomAttribute attribute)
+ {
+ var ctorArguments = attribute.ConstructorArguments;
+ return new SetupCompileInfo
+ {
+ OutputName = (string) ctorArguments [0].Value,
+ SourceFiles = SourceFilesForAttributeArgument (ctorArguments [1]),
+ References = ((CustomAttributeArgument []) ctorArguments [2].Value)?.Select (arg => arg.Value.ToString ()).ToArray (),
+ Defines = ((CustomAttributeArgument []) ctorArguments [3].Value)?.Select (arg => arg.Value.ToString ()).ToArray (),
+ Resources = ((CustomAttributeArgument []) ctorArguments [4].Value)?.Select (arg => MakeSourceTreeFilePathAbsolute (arg.Value.ToString ())).ToArray (),
+ AdditionalArguments = (string) ctorArguments [5].Value,
+ CompilerToUse = (string) ctorArguments [6].Value,
+ AddAsReference = ctorArguments.Count >= 8 ? (bool) ctorArguments [7].Value : true
+ };
+ }
+
+ protected NPath MakeSourceTreeFilePathAbsolute (string value)
+ {
+ return _testCase.SourceFile.Parent.Combine (value);
+ }
+
+ protected NPath[] SourceFilesForAttributeArgument (CustomAttributeArgument attributeArgument)
+ {
+ return ((CustomAttributeArgument []) attributeArgument.Value)
+ .Select (attributeArg => SourceFileForAttributeArgumentValue (attributeArg.Value))
+ .Distinct ()
+ .ToArray ();
+ }
+
+ protected virtual NPath SourceFileForAttributeArgumentValue (object value)
+ {
+ var valueAsTypeRef = value as TypeReference;
+ if (valueAsTypeRef != null) {
+ // Use the parent type for locating the source file
+ var parentType = ParentMostType (valueAsTypeRef);
+ var pathRelativeToAssembly = $"{parentType.FullName.Substring (parentType.Module.Name.Length - 3).Replace ('.', '/')}.cs".ToNPath ();
+ var pathElements = pathRelativeToAssembly.Elements.ToArray ();
+ var topMostDirectoryName = pathElements [0];
+ var topMostDirectory = _testCase.SourceFile.RecursiveParents.Reverse ().FirstOrDefault (d => !d.IsRoot && d.FileName == topMostDirectoryName);
+
+ if (topMostDirectory == null) {
+ // Before giving up, try and detect the naming scheme for tests that use a dot in the top level directory name.
+ // Ex:
+ // Attributes.Debugger
+ // + 1 because the file name is one of the elements
+ if (pathElements.Length >= 3) {
+ topMostDirectoryName = $"{pathElements[0]}.{pathElements[1]}";
+ topMostDirectory = _testCase.SourceFile.RecursiveParents.Reverse ().FirstOrDefault (d => !d.IsRoot && d.FileName == topMostDirectoryName);
+ pathRelativeToAssembly = topMostDirectoryName.ToNPath ().Combine (pathElements.Skip (2).Aggregate (new NPath (string.Empty), (path, s) => path.Combine (s)));
+ }
+
+ if (topMostDirectory == null)
+ throw new ArgumentException ($"Unable to locate the source file for type {valueAsTypeRef}. Could not locate directory {topMostDirectoryName}. Ensure the type name matches the file name. And the namespace match the directory structure on disk");
+ }
+
+ var fullPath = topMostDirectory.Parent.Combine (pathRelativeToAssembly);
+
+ if (!fullPath.Exists ())
+ throw new ArgumentException ($"Unable to locate the source file for type {valueAsTypeRef}. Expected {fullPath}. Ensure the type name matches the file name. And the namespace match the directory structure on disk");
+
+ return fullPath;
+ }
+
+ return MakeSourceTreeFilePathAbsolute (value.ToString ());
+ }
+
+ static TypeReference ParentMostType (TypeReference type)
+ {
+ if (!type.IsNested)
+ return type;
+
+ return ParentMostType (type.DeclaringType);
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestCaseSandbox.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseSandbox.cs
new file mode 100644
index 000000000..5ec502878
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestCaseSandbox.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Extensions;
+using Mono.Linker.Tests.TestCases;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class TestCaseSandbox {
+ protected readonly TestCase _testCase;
+ protected readonly NPath _directory;
+
+ public TestCaseSandbox (TestCase testCase)
+ : this (testCase, NPath.SystemTemp)
+ {
+ }
+
+ public TestCaseSandbox (TestCase testCase, NPath rootTemporaryDirectory)
+ : this (testCase, rootTemporaryDirectory, string.Empty)
+ {
+ }
+
+ public TestCaseSandbox (TestCase testCase, string rootTemporaryDirectory, string namePrefix)
+ : this (testCase, rootTemporaryDirectory.ToNPath (), namePrefix)
+ {
+ }
+
+ public TestCaseSandbox (TestCase testCase, NPath rootTemporaryDirectory, string namePrefix)
+ {
+ _testCase = testCase;
+ var name = string.IsNullOrEmpty (namePrefix) ? "linker_tests" : $"{namePrefix}_linker_tests";
+ _directory = rootTemporaryDirectory.Combine (name);
+
+ _directory.DeleteContents ();
+
+ InputDirectory = _directory.Combine ("input").EnsureDirectoryExists ();
+ OutputDirectory = _directory.Combine ("output").EnsureDirectoryExists ();
+ ExpectationsDirectory = _directory.Combine ("expectations").EnsureDirectoryExists ();
+ ResourcesDirectory = _directory.Combine ("resources").EnsureDirectoryExists ();
+ }
+
+ public NPath InputDirectory { get; }
+
+ public NPath OutputDirectory { get; }
+
+ public NPath ExpectationsDirectory { get; }
+
+ public NPath ResourcesDirectory { get; }
+
+ public IEnumerable<NPath> SourceFiles {
+ get { return _directory.Files ("*.cs"); }
+ }
+
+ public IEnumerable<NPath> LinkXmlFiles {
+ get { return InputDirectory.Files ("*.xml"); }
+ }
+
+ public IEnumerable<NPath> ResponseFiles {
+ get { return InputDirectory.Files ("*.rsp"); }
+ }
+
+ public IEnumerable<NPath> ResourceFiles => ResourcesDirectory.Files ();
+
+ public virtual void Populate (TestCaseMetadaProvider metadataProvider)
+ {
+ _testCase.SourceFile.Copy (_directory);
+
+ if (_testCase.HasLinkXmlFile)
+ _testCase.LinkXmlFile.Copy (InputDirectory);
+
+ CopyToInputAndExpectations (GetExpectationsAssemblyPath ());
+
+ foreach (var dep in metadataProvider.AdditionalFilesToSandbox ()) {
+ var destination = _directory.Combine (dep.DestinationFileName);
+ dep.Source.FileMustExist ().Copy (destination);
+
+ // In a few niche tests we need to copy pre-built assemblies directly into the input directory.
+ // When this is done, we also need to copy them into the expectations directory so that if they are used
+ // as references we can still compile the expectations version of the assemblies
+ if (destination.Parent == InputDirectory)
+ dep.Source.Copy (ExpectationsDirectory.Combine (destination.RelativeTo (InputDirectory)));
+ }
+
+ // Copy non class library dependencies to the sandbox
+ foreach (var fileName in metadataProvider.GetReferenceValues ()) {
+ if (!fileName.StartsWith ("System.", StringComparison.Ordinal) && !fileName.StartsWith ("Mono.", StringComparison.Ordinal) && !fileName.StartsWith ("Microsoft.", StringComparison.Ordinal))
+ CopyToInputAndExpectations (_testCase.SourceFile.Parent.Combine (fileName.ToNPath ()));
+ }
+
+ foreach (var referenceDependency in metadataProvider.GetReferenceDependencies ())
+ CopyToInputAndExpectations (_testCase.SourceFile.Parent.Combine (referenceDependency.ToNPath()));
+
+ foreach (var res in metadataProvider.GetResources ()) {
+ res.Source.FileMustExist ().Copy (ResourcesDirectory.Combine (res.DestinationFileName));
+ }
+
+ foreach (var res in metadataProvider.GetResponseFiles()) {
+ res.Source.FileMustExist ().Copy (InputDirectory.Combine (res.DestinationFileName));
+ }
+
+ foreach (var compileRefInfo in metadataProvider.GetSetupCompileAssembliesBefore ())
+ {
+ var destination = BeforeReferenceSourceDirectoryFor (compileRefInfo.OutputName).EnsureDirectoryExists ();
+ compileRefInfo.SourceFiles.Copy (destination);
+
+ destination = BeforeReferenceResourceDirectoryFor (compileRefInfo.OutputName).EnsureDirectoryExists ();
+ compileRefInfo.Resources?.Copy (destination);
+ }
+
+ foreach (var compileRefInfo in metadataProvider.GetSetupCompileAssembliesAfter ())
+ {
+ var destination = AfterReferenceSourceDirectoryFor (compileRefInfo.OutputName).EnsureDirectoryExists ();
+ compileRefInfo.SourceFiles.Copy (destination);
+
+ destination = AfterReferenceResourceDirectoryFor (compileRefInfo.OutputName).EnsureDirectoryExists ();
+ compileRefInfo.Resources?.Copy (destination);
+ }
+ }
+
+ private static NPath GetExpectationsAssemblyPath ()
+ {
+ return new Uri (typeof (KeptAttribute).Assembly.CodeBase).LocalPath.ToNPath ();
+ }
+
+ protected void CopyToInputAndExpectations (NPath source)
+ {
+ source.Copy (InputDirectory);
+ source.Copy (ExpectationsDirectory);
+ }
+
+ public NPath BeforeReferenceSourceDirectoryFor (string outputName)
+ {
+ return _directory.Combine ($"ref_source_before_{Path.GetFileNameWithoutExtension (outputName)}");
+ }
+
+ public NPath AfterReferenceSourceDirectoryFor (string outputName)
+ {
+ return _directory.Combine ($"ref_source_after_{Path.GetFileNameWithoutExtension (outputName)}");
+ }
+
+ public NPath BeforeReferenceResourceDirectoryFor (string outputName)
+ {
+ return _directory.Combine ($"ref_resource_before_{Path.GetFileNameWithoutExtension (outputName)}");
+ }
+
+ public NPath AfterReferenceResourceDirectoryFor (string outputName)
+ {
+ return _directory.Combine ($"ref_resource_after_{Path.GetFileNameWithoutExtension (outputName)}");
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs b/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs
new file mode 100644
index 000000000..fc421882e
--- /dev/null
+++ b/test/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Mono.Cecil;
+using Mono.Linker.Tests.Extensions;
+using Mono.Linker.Tests.TestCases;
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
+ public class TestRunner {
+ private readonly ObjectFactory _factory;
+
+ public TestRunner (ObjectFactory factory)
+ {
+ _factory = factory;
+ }
+
+ public virtual LinkedTestCaseResult Run (TestCase testCase)
+ {
+ using (var fullTestCaseAssemblyDefinition = AssemblyDefinition.ReadAssembly (testCase.OriginalTestCaseAssemblyPath.ToString ())) {
+ var metadataProvider = _factory.CreateMetadataProvider (testCase, fullTestCaseAssemblyDefinition);
+
+ string ignoreReason;
+ if (metadataProvider.IsIgnored (out ignoreReason))
+ Assert.Ignore (ignoreReason);
+
+ var sandbox = Sandbox (testCase, metadataProvider);
+ var compilationResult = Compile (sandbox, metadataProvider);
+ PrepForLink (sandbox, compilationResult);
+ return Link (testCase, sandbox, compilationResult, metadataProvider);
+ }
+ }
+
+ private TestCaseSandbox Sandbox (TestCase testCase, TestCaseMetadaProvider metadataProvider)
+ {
+ var sandbox = _factory.CreateSandbox (testCase);
+ sandbox.Populate (metadataProvider);
+ return sandbox;
+ }
+
+ private ManagedCompilationResult Compile (TestCaseSandbox sandbox, TestCaseMetadaProvider metadataProvider)
+ {
+ var inputCompiler = _factory.CreateCompiler (sandbox, metadataProvider);
+ var expectationsCompiler = _factory.CreateCompiler (sandbox, metadataProvider);
+ var sourceFiles = sandbox.SourceFiles.Select(s => s.ToString()).ToArray();
+
+ var assemblyName = metadataProvider.GetAssemblyName ();
+
+ var commonReferences = metadataProvider.GetCommonReferencedAssemblies(sandbox.InputDirectory).ToArray ();
+ var mainAssemblyReferences = metadataProvider.GetReferencedAssemblies(sandbox.InputDirectory).ToArray ();
+ var resources = sandbox.ResourceFiles.ToArray ();
+ var additionalArguments = metadataProvider.GetSetupCompilerArguments ().ToArray ();
+
+ var expectationsCommonReferences = metadataProvider.GetCommonReferencedAssemblies (sandbox.ExpectationsDirectory).ToArray ();
+ var expectationsMainAssemblyReferences = metadataProvider.GetReferencedAssemblies (sandbox.ExpectationsDirectory).ToArray ();
+
+ var inputTask = Task.Run(() => inputCompiler.CompileTestIn (sandbox.InputDirectory, assemblyName, sourceFiles, commonReferences, mainAssemblyReferences, null, resources, additionalArguments));
+ var expectationsTask = Task.Run(() => expectationsCompiler.CompileTestIn (sandbox.ExpectationsDirectory, assemblyName, sourceFiles, expectationsCommonReferences, expectationsMainAssemblyReferences, new[] {"INCLUDE_EXPECTATIONS"}, resources, additionalArguments));
+
+ NPath inputAssemblyPath = null;
+ NPath expectationsAssemblyPath = null;
+ try {
+ inputAssemblyPath = GetResultOfTaskThatMakesNUnitAssertions (inputTask);
+ expectationsAssemblyPath = GetResultOfTaskThatMakesNUnitAssertions (expectationsTask);
+ } catch (Exception) {
+ // If completing the input assembly task threw, we need to wait for the expectations task to complete before continuing
+ // otherwise we could set the next test up for a race condition with the expectations compilation over access to the sandbox directory
+ if (inputAssemblyPath == null && expectationsAssemblyPath == null)
+ {
+ try {
+ expectationsTask.Wait ();
+ } catch (Exception) {
+ // Don't care, we want to throw the first exception
+ }
+ }
+
+ throw;
+ }
+ return new ManagedCompilationResult (inputAssemblyPath, expectationsAssemblyPath);
+ }
+
+ protected virtual void PrepForLink (TestCaseSandbox sandbox, ManagedCompilationResult compilationResult)
+ {
+ }
+
+ private LinkedTestCaseResult Link (TestCase testCase, TestCaseSandbox sandbox, ManagedCompilationResult compilationResult, TestCaseMetadaProvider metadataProvider)
+ {
+ var linker = _factory.CreateLinker ();
+ var builder = _factory.CreateLinkerArgumentBuilder (metadataProvider);
+
+ AddLinkOptions (sandbox, compilationResult, builder, metadataProvider);
+
+ linker.Link (builder.ToArgs ());
+
+ return new LinkedTestCaseResult (testCase, compilationResult.InputAssemblyPath, sandbox.OutputDirectory.Combine (compilationResult.InputAssemblyPath.FileName), compilationResult.ExpectationsAssemblyPath);
+ }
+
+ protected virtual void AddLinkOptions (TestCaseSandbox sandbox, ManagedCompilationResult compilationResult, LinkerArgumentBuilder builder, TestCaseMetadaProvider metadataProvider)
+ {
+ var caseDefinedOptions = metadataProvider.GetLinkerOptions ();
+
+ builder.AddOutputDirectory (sandbox.OutputDirectory);
+ foreach (var linkXmlFile in sandbox.LinkXmlFiles)
+ builder.AddLinkXmlFile (linkXmlFile);
+
+ foreach (var linkXmlFile in sandbox.ResponseFiles)
+ builder.AddResponseFile (linkXmlFile);
+
+ builder.AddSearchDirectory (sandbox.InputDirectory);
+ foreach (var extraSearchDir in metadataProvider.GetExtraLinkerSearchDirectories ())
+ builder.AddSearchDirectory (extraSearchDir);
+
+ builder.ProcessOptions (caseDefinedOptions);
+
+ builder.ProcessTestInputAssembly (compilationResult.InputAssemblyPath);
+ }
+
+ private T GetResultOfTaskThatMakesNUnitAssertions<T> (Task<T> task)
+ {
+ try {
+ return task.Result;
+ } catch (AggregateException e) {
+ if (e.InnerException != null) {
+ if (e.InnerException is AssertionException
+ || e.InnerException is SuccessException
+ || e.InnerException is IgnoreException
+ || e.InnerException is InconclusiveException)
+ throw e.InnerException;
+ }
+
+ throw;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs b/test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs
new file mode 100644
index 000000000..c8c407520
--- /dev/null
+++ b/test/Mono.Linker.Tests/Tests/ParseResponseFileLinesTests.cs
@@ -0,0 +1,69 @@
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace Mono.Linker.Tests {
+ [TestFixture]
+ public class ParseResponseFileLinesTests {
+ [Test]
+ public void TestOneArg ()
+ {
+ TestParseResponseFileLines (@"abc", new string [] { @"abc" });
+ }
+
+ [Test]
+ public void TestTwoArgsOnOneLine ()
+ {
+ TestParseResponseFileLines (@"abc def", new string [] { @"abc", @"def" });
+ }
+
+ [Test]
+ public void TestTwoArgsOnTwoLine ()
+ {
+ TestParseResponseFileLines (@"abc
+def", new string [] { @"abc", @"def" });
+ }
+
+ [Test]
+ public void TestOneSlashWithoutQuote ()
+ {
+ TestParseResponseFileLines (@"\", new string [] { @"\" });
+ }
+
+ [Test]
+ public void TestTwoSlashesWithoutQuote ()
+ {
+ TestParseResponseFileLines (@"\\", new string [] { @"\\" });
+ }
+
+ [Test]
+ public void TestOneSlashWithQuote ()
+ {
+ TestParseResponseFileLines (@"""x \"" y""", new string [] { @"x "" y" });
+ }
+
+ [Test]
+ public void TestTwoSlashesWithQuote ()
+ {
+ TestParseResponseFileLines (@"""Trailing Slash\\""", new string [] { @"Trailing Slash\" });
+ }
+
+ [Test]
+ public void TestWindowsPath ()
+ {
+ TestParseResponseFileLines (@"C:\temp\test.txt", new string [] { @"C:\temp\test.txt" });
+ }
+
+ [Test]
+ public void TestLinuxPath ()
+ {
+ TestParseResponseFileLines (@"/tmp/test.txt", new string [] { @"/tmp/test.txt" });
+ }
+
+ private void TestParseResponseFileLines (string v1, string [] v2)
+ {
+ var result = new Queue<string> ();
+ Driver.ParseResponseFileLines (v1.Split ('\n'), result);
+ Assert.That (result, Is.EquivalentTo (v2));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/Tests/PreserveActionComparisonTests.cs b/test/Mono.Linker.Tests/Tests/PreserveActionComparisonTests.cs
new file mode 100644
index 000000000..21c881468
--- /dev/null
+++ b/test/Mono.Linker.Tests/Tests/PreserveActionComparisonTests.cs
@@ -0,0 +1,30 @@
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests
+{
+ [TestFixture]
+ public class PreserveActionComparisonTests
+ {
+ [TestCase (TypePreserve.All, TypePreserve.All, TypePreserve.All)]
+ [TestCase (TypePreserve.All, TypePreserve.Methods, TypePreserve.All)]
+ [TestCase (TypePreserve.All, TypePreserve.Fields, TypePreserve.All)]
+ [TestCase (TypePreserve.All, TypePreserve.Nothing, TypePreserve.All)]
+ [TestCase (TypePreserve.Methods, TypePreserve.All, TypePreserve.All)]
+ [TestCase (TypePreserve.Methods, TypePreserve.Methods, TypePreserve.Methods)]
+ [TestCase (TypePreserve.Methods, TypePreserve.Fields, TypePreserve.All)]
+ [TestCase (TypePreserve.Methods, TypePreserve.Nothing, TypePreserve.Methods)]
+ [TestCase (TypePreserve.Fields, TypePreserve.All, TypePreserve.All)]
+ [TestCase (TypePreserve.Fields, TypePreserve.Methods, TypePreserve.All)]
+ [TestCase (TypePreserve.Fields, TypePreserve.Fields, TypePreserve.Fields)]
+ [TestCase (TypePreserve.Fields, TypePreserve.Nothing, TypePreserve.Fields)]
+ [TestCase (TypePreserve.Nothing, TypePreserve.All, TypePreserve.All)]
+ [TestCase (TypePreserve.Nothing, TypePreserve.Methods, TypePreserve.Methods)]
+ [TestCase (TypePreserve.Nothing, TypePreserve.Fields, TypePreserve.Fields)]
+ [TestCase (TypePreserve.Nothing, TypePreserve.Nothing, TypePreserve.Nothing)]
+ public void VerifyBehaviorOfChoosePreserveActionWhichPreservesTheMost (TypePreserve left, TypePreserve right, TypePreserve expected)
+ {
+ Assert.That (expected, Is.EqualTo (AnnotationStore.ChoosePreserveActionWhichPreservesTheMost (left, right)));
+ Assert.That (expected, Is.EqualTo (AnnotationStore.ChoosePreserveActionWhichPreservesTheMost (right, left)));
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests/Tests/TypeNameParserTests.cs b/test/Mono.Linker.Tests/Tests/TypeNameParserTests.cs
new file mode 100644
index 000000000..b5d124619
--- /dev/null
+++ b/test/Mono.Linker.Tests/Tests/TypeNameParserTests.cs
@@ -0,0 +1,121 @@
+using NUnit.Framework;
+
+namespace Mono.Linker.Tests {
+ [TestFixture]
+ public class TypeNameParserTests {
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_Null ()
+ {
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (null, out string typeName, out string assemblyName), Is.False);
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_FullyQualified ()
+ {
+ var value = typeof (TypeNameParserTests).AssemblyQualifiedName;
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo (typeof (TypeNameParserTests).FullName));
+ Assert.That (assemblyName, Is.EqualTo (typeof (TypeNameParserTests).Assembly.GetName ().Name));
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_NameAndAssemblyOnly ()
+ {
+ var value = $"{typeof (TypeNameParserTests).FullName}, {typeof (TypeNameParserTests).Assembly.GetName ().Name}";
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo (typeof (TypeNameParserTests).FullName));
+ Assert.That (assemblyName, Is.EqualTo (typeof (TypeNameParserTests).Assembly.GetName ().Name));
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_NameOnly ()
+ {
+ var value = typeof (TypeNameParserTests).FullName;
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo (typeof (TypeNameParserTests).FullName));
+ Assert.That (assemblyName, Is.Null);
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_GenericType_FullyQualified ()
+ {
+ var value = typeof (SampleGenericType<,>).AssemblyQualifiedName;
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo($"{typeof (TypeNameParserTests).FullName}/SampleGenericType`2"));
+ Assert.That (assemblyName, Is.EqualTo(typeof (TypeNameParserTests).Assembly.GetName ().Name));
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_GenericType_NameAndAssemblyOnly ()
+ {
+ var value = $"{typeof (SampleGenericType<,>).FullName}, {typeof (TypeNameParserTests).Assembly.GetName ().Name}";
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo ($"{typeof (TypeNameParserTests).FullName}/SampleGenericType`2"));
+ Assert.That (assemblyName, Is.EqualTo (typeof (TypeNameParserTests).Assembly.GetName ().Name));
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_GenericType_NameOnly ()
+ {
+ var value = typeof (SampleGenericType<,>).FullName;
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo ($"{typeof (TypeNameParserTests).FullName}/SampleGenericType`2"));
+ Assert.That (assemblyName, Is.Null);
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_NestedType_FullyQualified ()
+ {
+ var value = typeof (SampleNestedType).AssemblyQualifiedName;
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo($"{typeof (TypeNameParserTests).FullName}/{nameof (SampleNestedType)}"));
+ Assert.That (assemblyName, Is.EqualTo(typeof (TypeNameParserTests).Assembly.GetName ().Name));
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_NestedType_NameAndAssemblyOnly ()
+ {
+ var value = $"{typeof (SampleNestedType).FullName}, {typeof (TypeNameParserTests).Assembly.GetName().Name}";
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo ($"{typeof (TypeNameParserTests).FullName}/{nameof (SampleNestedType)}"));
+ Assert.That (assemblyName, Is.EqualTo (typeof (TypeNameParserTests).Assembly.GetName ().Name));
+ }
+
+ [Test]
+ public void TryParseTypeAssemblyQualifiedName_NestedType_NameOnly ()
+ {
+ var value = typeof (SampleNestedType).FullName;
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (value, out string typeName, out string assemblyName), Is.True);
+ Assert.That (typeName, Is.EqualTo ($"{typeof (TypeNameParserTests).FullName}/{nameof (SampleNestedType)}"));
+ Assert.That (assemblyName, Is.Null);
+ }
+
+ [Test]
+ public void MissingTypeName ()
+ {
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (", System", out string typeName, out string assemblyName), Is.False);
+ Assert.That (typeName, Is.Null);
+ Assert.That (assemblyName, Is.Null);
+ }
+
+
+ [TestCase ("A[]][")]
+ [TestCase ("A][")]
+ [TestCase ("A[")]
+ [TestCase (", , ")]
+ [TestCase (", , , ")]
+ [TestCase (", , , , ")]
+ public void InvalidValues (string name)
+ {
+ Assert.That (TypeNameParser.TryParseTypeAssemblyQualifiedName (name, out string typeName, out string assemblyName), Is.False);
+ Assert.That (typeName, Is.Null);
+ Assert.That (assemblyName, Is.Null);
+ }
+
+ class SampleNestedType {
+ }
+
+ class SampleGenericType<T1, T2> {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/Mono.Linker.Tests/packages.config b/test/Mono.Linker.Tests/packages.config
new file mode 100644
index 000000000..e49d840c2
--- /dev/null
+++ b/test/Mono.Linker.Tests/packages.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="3.6.1" targetFramework="net462" />
+ <package id="NUnit.ConsoleRunner" version="3.6.1" targetFramework="net462" />
+ <package id="NUnit.Extension.NUnitV2ResultWriter" version="3.5.0" targetFramework="net462" />
+</packages>