You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			204 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
 | |
| 
 | |
| using System;
 | |
| using System.Collections;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using System.Reflection;
 | |
| using Xunit.Extensions;
 | |
| 
 | |
| namespace Microsoft.TestCommon
 | |
| {
 | |
|     public class TestDataSetAttribute : DataAttribute
 | |
|     {
 | |
|         public Type DeclaringType { get; set; }
 | |
| 
 | |
|         public string PropertyName { get; set; }
 | |
| 
 | |
|         public TestDataVariations TestDataVariations { get; set; }
 | |
| 
 | |
|         private IEnumerable<Tuple<Type, string>> ExtraDataSets { get; set; }
 | |
| 
 | |
|         public TestDataSetAttribute(Type declaringType, string propertyName, TestDataVariations testDataVariations = TestCommon.TestDataVariations.All)
 | |
|         {
 | |
|             DeclaringType = declaringType;
 | |
|             PropertyName = propertyName;
 | |
|             TestDataVariations = testDataVariations;
 | |
|             ExtraDataSets = new List<Tuple<Type, string>>();
 | |
|         }
 | |
| 
 | |
|         public TestDataSetAttribute(Type declaringType, string propertyName,
 | |
|                                     Type declaringType1, string propertyName1,
 | |
|                                     TestDataVariations testDataVariations = TestCommon.TestDataVariations.All)
 | |
|             : this(declaringType, propertyName, testDataVariations)
 | |
|         {
 | |
|             ExtraDataSets = new List<Tuple<Type, string>> { Tuple.Create(declaringType1, propertyName1) };
 | |
|         }
 | |
| 
 | |
|         public TestDataSetAttribute(Type declaringType, string propertyName,
 | |
|             Type declaringType1, string propertyName1,
 | |
|             Type declaringType2, string propertyName2,
 | |
|             TestDataVariations testDataVariations = TestCommon.TestDataVariations.All)
 | |
|             : this(declaringType, propertyName, testDataVariations)
 | |
|         {
 | |
|             ExtraDataSets = new List<Tuple<Type, string>> { Tuple.Create(declaringType1, propertyName1), Tuple.Create(declaringType2, propertyName2) };
 | |
|         }
 | |
| 
 | |
|         public TestDataSetAttribute(Type declaringType, string propertyName,
 | |
|             Type declaringType1, string propertyName1,
 | |
|             Type declaringType2, string propertyName2,
 | |
|             Type declaringType3, string propertyName3,
 | |
|             TestDataVariations testDataVariations = TestCommon.TestDataVariations.All)
 | |
|             : this(declaringType, propertyName, testDataVariations)
 | |
|         {
 | |
|             ExtraDataSets = new List<Tuple<Type, string>> { Tuple.Create(declaringType1, propertyName1), Tuple.Create(declaringType2, propertyName2), Tuple.Create(declaringType3, propertyName3) };
 | |
|         }
 | |
| 
 | |
|         public TestDataSetAttribute(Type declaringType, string propertyName,
 | |
|             Type declaringType1, string propertyName1,
 | |
|             Type declaringType2, string propertyName2,
 | |
|             Type declaringType3, string propertyName3,
 | |
|             Type declaringType4, string propertyName4,
 | |
|             TestDataVariations testDataVariations = TestCommon.TestDataVariations.All)
 | |
|             : this(declaringType, propertyName, testDataVariations)
 | |
|         {
 | |
|             ExtraDataSets = new List<Tuple<Type, string>> 
 | |
|             { 
 | |
|                 Tuple.Create(declaringType1, propertyName1), Tuple.Create(declaringType2, propertyName2), 
 | |
|                 Tuple.Create(declaringType3, propertyName3), Tuple.Create(declaringType4, propertyName4) 
 | |
|             };
 | |
|         }
 | |
| 
 | |
|         public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest, Type[] parameterTypes)
 | |
|         {
 | |
|             IEnumerable<object[]> baseDataSet = GetBaseDataSet(DeclaringType, PropertyName, TestDataVariations);
 | |
|             IEnumerable<IEnumerable<object[]>> extraDataSets = GetExtraDataSets();
 | |
| 
 | |
|             IEnumerable<IEnumerable<object[]>> finalDataSets = (new[] { baseDataSet }).Concat(extraDataSets);
 | |
| 
 | |
|             var datasets = CrossProduct(finalDataSets);
 | |
| 
 | |
|             return datasets;
 | |
|         }
 | |
| 
 | |
|         private static IEnumerable<object[]> CrossProduct(IEnumerable<IEnumerable<object[]>> datasets)
 | |
|         {
 | |
|             if (datasets.Count() == 1)
 | |
|             {
 | |
|                 foreach (var dataset in datasets.First())
 | |
|                 {
 | |
|                     yield return dataset;
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 IEnumerable<object[]> datasetLeft = datasets.First();
 | |
|                 IEnumerable<object[]> datasetRight = CrossProduct(datasets.Skip(1));
 | |
| 
 | |
|                 foreach (var dataLeft in datasetLeft)
 | |
|                 {
 | |
|                     foreach (var dataRight in datasetRight)
 | |
|                     {
 | |
|                         yield return dataLeft.Concat(dataRight).ToArray();
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // The base data set(first one) can either be a TestDataSet or a TestDataSetCollection
 | |
|         private static IEnumerable<object[]> GetBaseDataSet(Type declaringType, string propertyName, TestDataVariations variations)
 | |
|         {
 | |
|             return TryGetDataSetFromTestDataCollection(declaringType, propertyName, variations) ?? GetDataSet(declaringType, propertyName);
 | |
|         }
 | |
| 
 | |
|         private IEnumerable<IEnumerable<object[]>> GetExtraDataSets()
 | |
|         {
 | |
|             foreach (var tuple in ExtraDataSets)
 | |
|             {
 | |
|                 yield return GetDataSet(tuple.Item1, tuple.Item2);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private static object GetTestDataPropertyValue(Type declaringType, string propertyName)
 | |
|         {
 | |
|             PropertyInfo property = declaringType.GetProperty(propertyName, BindingFlags.Static | BindingFlags.Public);
 | |
| 
 | |
|             if (property == null)
 | |
|             {
 | |
|                 throw new ArgumentException(string.Format("Could not find public static property {0} on {1}", propertyName, declaringType.FullName));
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 return property.GetValue(null, null);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private static IEnumerable<object[]> GetDataSet(Type declaringType, string propertyName)
 | |
|         {
 | |
|             object propertyValue = GetTestDataPropertyValue(declaringType, propertyName);
 | |
| 
 | |
|             // box the dataset items if the property is not a RefTypeTestData 
 | |
|             IEnumerable<object> value = (propertyValue as IEnumerable<object>) ?? (propertyValue as IEnumerable).Cast<object>();
 | |
|             if (value == null)
 | |
|             {
 | |
|                 throw new InvalidOperationException(string.Format("{0}.{1} is either null or does not implement IEnumerable", declaringType.FullName, propertyName));
 | |
|             }
 | |
| 
 | |
|             IEnumerable<object[]> dataset = value as IEnumerable<object[]>;
 | |
|             if (dataset != null)
 | |
|             {
 | |
|                 return dataset;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 return value.Select((data) => new object[] { data });
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private static IEnumerable<object[]> TryGetDataSetFromTestDataCollection(Type declaringType, string propertyName, TestDataVariations variations)
 | |
|         {
 | |
|             object propertyValue = GetTestDataPropertyValue(declaringType, propertyName);
 | |
| 
 | |
|             IEnumerable<TestData> testDataCollection = propertyValue as IEnumerable<TestData>;
 | |
| 
 | |
|             return testDataCollection == null ? null : GetDataSetFromTestDataCollection(testDataCollection, variations);
 | |
|         }
 | |
| 
 | |
|         private static IEnumerable<object[]> GetDataSetFromTestDataCollection(IEnumerable<TestData> testDataCollection, TestDataVariations variations)
 | |
|         {
 | |
|             foreach (TestData testdataInstance in testDataCollection)
 | |
|             {
 | |
|                 foreach (TestDataVariations variation in testdataInstance.GetSupportedTestDataVariations())
 | |
|                 {
 | |
|                     if ((variation & variations) == variation)
 | |
|                     {
 | |
|                         Type variationType = testdataInstance.GetAsTypeOrNull(variation);
 | |
|                         object testData = testdataInstance.GetAsTestDataOrNull(variation);
 | |
|                         if (AsSingleInstances(variation))
 | |
|                         {
 | |
|                             foreach (object obj in (IEnumerable)testData)
 | |
|                             {
 | |
|                                 yield return new object[] { variationType, obj };
 | |
|                             }
 | |
|                         }
 | |
|                         else
 | |
|                         {
 | |
|                             yield return new object[] { variationType, testData };
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private static bool AsSingleInstances(TestDataVariations variation)
 | |
|         {
 | |
|             return variation == TestDataVariations.AsInstance ||
 | |
|                    variation == TestDataVariations.AsNullable ||
 | |
|                    variation == TestDataVariations.AsDerivedType ||
 | |
|                    variation == TestDataVariations.AsKnownType ||
 | |
|                    variation == TestDataVariations.AsDataMember ||
 | |
|                    variation == TestDataVariations.AsXmlElementProperty;
 | |
|         }
 | |
|     }
 | |
| }
 |