diff --git a/src/libraries/System.Data.Common/src/ILLink/ILLink.Descriptors.LibraryBuild.xml b/src/libraries/System.Data.Common/src/ILLink/ILLink.Descriptors.LibraryBuild.xml new file mode 100644 index 0000000000000..057b8b37f8367 --- /dev/null +++ b/src/libraries/System.Data.Common/src/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Data.Common/tests/System/Data/DataColumnTest.cs b/src/libraries/System.Data.Common/tests/System/Data/DataColumnTest.cs index 8e318d2d13808..6f823a1561965 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/DataColumnTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/DataColumnTest.cs @@ -33,7 +33,7 @@ using System.ComponentModel; using System.Data.SqlTypes; - +using System.Reflection; using Xunit; namespace System.Data.Tests @@ -793,6 +793,54 @@ public void NonSqlNullableType_RequiresPublicStaticNull() Assert.Throws(() => t.Columns.Add("c3", typeof(NullableTypeWithoutNullMember))); } + [Fact] + public void MethodsCalledByReflectionSerializersAreNotTrimmed() + { + Assert.True(ShouldSerializeExists(nameof(DataColumn.Caption))); + Assert.True(ShouldSerializeExists(nameof(DataColumn.DefaultValue))); + Assert.True(ShouldSerializeExists(nameof(DataColumn.Namespace))); + + Assert.True(ResetExists(nameof(DataColumn.Caption))); + Assert.False(ResetExists(nameof(DataColumn.DefaultValue))); + Assert.True(ResetExists(nameof(DataColumn.Namespace))); + + bool ShouldSerializeExists(string name) => typeof(DataColumn).GetMethod("ShouldSerialize" + name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null; + bool ResetExists(string name) => typeof(DataColumn).GetMethod("Reset" + name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null; + } + + [Fact] + public void MethodsCalledByReflectionSerializersAreNotTrimmedUsingTypeDescriptor() + { + DataColumn dc = new DataColumn + { + ColumnName = "dataColumn", + DataType = typeof(DateTime) + }; + + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(dc); + + Assert.False(properties[nameof(DataColumn.DefaultValue)].ShouldSerializeValue(dc)); + dc.DefaultValue = DateTime.MinValue; + Assert.True(properties[nameof(DataColumn.DefaultValue)].ShouldSerializeValue(dc)); + properties[nameof(DataColumn.DefaultValue)].ResetValue(dc); + Assert.Equal(DateTime.MinValue, dc.DefaultValue); + Assert.True(properties[nameof(DataColumn.DefaultValue)].ShouldSerializeValue(dc)); + + Assert.False(properties[nameof(DataColumn.Caption)].ShouldSerializeValue(dc)); + dc.Caption = "Caption"; + Assert.True(properties[nameof(DataColumn.Caption)].ShouldSerializeValue(dc)); + properties[nameof(DataColumn.Caption)].ResetValue(dc); + Assert.False(properties[nameof(DataColumn.Caption)].ShouldSerializeValue(dc)); + Assert.Equal("dataColumn", dc.Caption); + + Assert.False(properties[nameof(DataColumn.Namespace)].ShouldSerializeValue(dc)); + dc.Namespace = "Namespace"; + Assert.True(properties[nameof(DataColumn.Namespace)].ShouldSerializeValue(dc)); + properties[nameof(DataColumn.Namespace)].ResetValue(dc); + Assert.False(properties[nameof(DataColumn.Namespace)].ShouldSerializeValue(dc)); + Assert.Equal("", dc.Namespace); + } + private sealed class NullableTypeWithNullProperty : INullable { public bool IsNull => true; diff --git a/src/libraries/System.Data.Common/tests/System/Data/DataRowTest.cs b/src/libraries/System.Data.Common/tests/System/Data/DataRowTest.cs index 5dd1ba770cc5f..07acb864750f2 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/DataRowTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/DataRowTest.cs @@ -29,7 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // - +using System.Reflection; using Xunit; namespace System.Data.Tests @@ -876,5 +876,15 @@ public void SetParent_missing_ParentRow() Assert.Equal(DBNull.Value, childRow[childColumn1]); Assert.Equal("value", childRow[childColumn2]); } + + [Fact] + public void MethodsCalledByReflectionSerializersAreNotTrimmed() + { + Assert.False(ShouldSerializeExists("LastChangedColumn")); + Assert.True(ResetExists("LastChangedColumn")); + + bool ShouldSerializeExists(string name) => typeof(DataRow).GetProperty("ShouldSerialize" + name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null; + bool ResetExists(string name) => typeof(DataRow).GetMethod("Reset" + name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null; + } } } diff --git a/src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs b/src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs index f8edbc0491e6f..0c9a4dc2a8fbc 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/DataSetTest.cs @@ -41,6 +41,7 @@ using Microsoft.DotNet.RemoteExecutor; using Xunit; using System.Tests; +using System.Reflection; namespace System.Data.Tests { @@ -1621,6 +1622,21 @@ static void RunTest() } } + [Fact] + public void MethodsCalledByReflectionSerializersAreNotTrimmed() + { + Assert.True(ShouldSerializeExists(nameof(DataSet.Relations))); + Assert.True(ShouldSerializeExists(nameof(DataSet.Tables))); + Assert.True(ShouldSerializeExists(nameof(DataSet.Locale))); + + Assert.True(ResetExists(nameof(DataSet.Relations))); + Assert.True(ResetExists(nameof(DataSet.Tables))); + Assert.False(ResetExists(nameof(DataSet.Locale))); + + bool ShouldSerializeExists(string name) => typeof(DataSet).GetMethod("ShouldSerialize" + name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null; + bool ResetExists(string name) => typeof(DataSet).GetMethod("Reset" + name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null; + } + #region DataSet.CreateDataReader Tests and DataSet.Load Tests private DataSet _ds; diff --git a/src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs b/src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs index bc032b1208fc7..4fb880b51ea3c 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/DataTableTest.cs @@ -33,6 +33,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; +using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Tests; using System.Tests; @@ -1818,6 +1819,60 @@ public void TableInitializedEventTest4() dt.Initialized -= new EventHandler(OnTableInitialized); } + [Fact] + public void MethodsCalledByReflectionSerializersAreNotTrimmed() + { + Assert.True(ShouldSerializeExists(nameof(DataTable.CaseSensitive))); + Assert.False(ShouldSerializeExists("Columns")); + Assert.False(ShouldSerializeExists("Constraints")); + Assert.False(ShouldSerializeExists("Indexes")); + Assert.True(ShouldSerializeExists(nameof(DataTable.Locale))); + Assert.True(ShouldSerializeExists(nameof(DataTable.Namespace))); + Assert.True(ShouldSerializeExists(nameof(DataTable.PrimaryKey))); + + Assert.True(ResetExists(nameof(DataTable.CaseSensitive))); + Assert.True(ResetExists("Columns")); + Assert.True(ResetExists("Constraints")); + Assert.True(ResetExists("Indexes")); + Assert.False(ResetExists(nameof(DataTable.Locale))); + Assert.True(ResetExists(nameof(DataTable.Namespace))); + Assert.True(ResetExists(nameof(DataTable.PrimaryKey))); + + bool ShouldSerializeExists(string name) => typeof(DataTable).GetMethod("ShouldSerialize" + name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null; + bool ResetExists(string name) => typeof(DataTable).GetMethod("Reset" + name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) != null; + } + + [Fact] + public void MethodsCalledByReflectionSerializersAreNotTrimmedUsingTypeDescriptor() + { + DataTable dt = new DataTable(); + dt.CaseSensitive = true; + dt.Locale = new CultureInfo("en-US"); + dt.PrimaryKey = new DataColumn[] { dt.Columns.Add("id", typeof(int)) }; + dt.Namespace = "NS"; + + PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(dt); + + Assert.True(properties[nameof(DataTable.PrimaryKey)].ShouldSerializeValue(dt)); + properties[nameof(DataTable.PrimaryKey)].ResetValue(dt); + Assert.False(properties[nameof(DataTable.PrimaryKey)].ShouldSerializeValue(dt)); + Assert.Equal(0, dt.PrimaryKey.Length); + + Assert.True(properties[nameof(DataTable.CaseSensitive)].ShouldSerializeValue(dt)); + properties[nameof(DataTable.CaseSensitive)].ResetValue(dt); + Assert.False(properties[nameof(DataTable.CaseSensitive)].ShouldSerializeValue(dt)); + Assert.False(dt.CaseSensitive); + + Assert.True(properties[nameof(DataTable.Locale)].ShouldSerializeValue(dt)); + properties[nameof(DataTable.Locale)].ResetValue(dt); + Assert.True(properties[nameof(DataTable.Locale)].ShouldSerializeValue(dt)); // Reset method is not available + + Assert.True(properties[nameof(DataTable.Namespace)].ShouldSerializeValue(dt)); + properties[nameof(DataTable.Namespace)].ResetValue(dt); + Assert.False(properties[nameof(DataTable.Namespace)].ShouldSerializeValue(dt)); + Assert.Equal("", dt.Namespace); + } + private void OnTableInitialized(object src, EventArgs args) { _tableInitialized = true;