From a38e870716988c3efdc7756037c1b0925eb279ea Mon Sep 17 00:00:00 2001 From: youssef-backport-bot Date: Thu, 16 Jan 2025 16:18:18 +0100 Subject: [PATCH] [rel/3.7] Fix tuple regression before it's shipped :) (#4679) Co-authored-by: Youssef1313 --- .../DataSource/DynamicDataOperations.cs | 13 +++++--- .../TupleDynamicDataTests.cs | 30 +++++++++++++++++-- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataOperations.cs b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataOperations.cs index 5272ae5c21..2f6ecf9698 100644 --- a/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataOperations.cs +++ b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataOperations.cs @@ -161,6 +161,13 @@ private static bool TryGetData(object dataSource, [NotNullWhen(true)] out IEnume objects.Add(array); + static object GetFieldOrProperty(Type type, object data, string fieldOrPropertyName) + // ValueTuple is a value type, and uses fields for Items. + // Tuple is a reference type, and uses properties for Items. + => type.IsValueType + ? type.GetField(fieldOrPropertyName).GetValue(data) + : type.GetProperty(fieldOrPropertyName).GetValue(data); + static void ProcessTuple(object data, object[] array, int startingIndex) { Type type = data.GetType(); @@ -170,13 +177,11 @@ static void ProcessTuple(object data, object[] array, int startingIndex) if (i != 7) { // Note: ItemN are properties on Tuple, but are fields on ValueTuple - array[startingIndex + i] = type.GetField($"Item{i + 1}")?.GetValue(data) - ?? type.GetProperty($"Item{i + 1}").GetValue(data); + array[startingIndex + i] = GetFieldOrProperty(type, data, $"Item{i + 1}"); continue; } - object rest = type.GetProperty("Rest")?.GetValue(data) ?? - type.GetField("Rest").GetValue(data)!; + object rest = GetFieldOrProperty(type, data, "Rest"); if (IsTupleOrValueTuple(rest, out _)) { ProcessTuple(rest, array, startingIndex + 7); diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/TupleDynamicDataTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/TupleDynamicDataTests.cs index 883369ae79..377f712419 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/TupleDynamicDataTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/TupleDynamicDataTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.Testing.Platform.Acceptance.IntegrationTests; @@ -33,8 +33,12 @@ public async Task CanUseLongTuplesAndValueTuplesForAllFrameworks(string tfm) 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 + Hello, , World + Hello2, , World2 + Hello, , World + Hello2, , World2 """); - testHostResult.AssertOutputContainsSummary(failed: 0, passed: 8, skipped: 0); + testHostResult.AssertOutputContainsSummary(failed: 0, passed: 12, skipped: 0); } [TestFixture(TestFixtureSharingStrategy.PerTestGroup)] @@ -91,11 +95,19 @@ public void TestMethod1(int p1, int p2, int p3, int p4, int p5, int p6, int p7, [DynamicData(nameof(DataTuple10))] [DynamicData(nameof(DataValueTuple10))] [TestMethod] - public void TestMethod1(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10) + public void TestMethod2(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10) { s_builder.AppendLine($"{p1}, {p2}, {p3}, {p4}, {p5}, {p6}, {p7}, {p8}, {p9}, {p10}"); } + [DynamicData(nameof(DataTupleString3))] + [DynamicData(nameof(DataValueTupleString3))] + [TestMethod] + public void TestMethod3(string p1, string p2, string p3) + { + s_builder.AppendLine($"{p1}, {p2}, {p3}"); + } + public static IEnumerable>> DataTuple8 => [ (1, 2, 3, 4, 5, 6, 7, 8).ToTuple(), @@ -119,6 +131,18 @@ public void TestMethod1(int p1, int p2, int p3, int p4, int p5, int p6, int p7, (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (11, 12, 13, 14, 15, 16, 17, 18, 19, 20), ]; + + public static IEnumerable> DataTupleString3 => + [ + ("Hello", (string)null, "World").ToTuple(), + ("Hello2", (string)null, "World2").ToTuple(), + ]; + + public static IEnumerable> DataValueTupleString3 => + [ + ("Hello", null, "World"), + ("Hello2", null, "World2"), + ]; }