// ***********************************************************************
// Copyright (c) 2008-2015 Charlie Poole
//
// 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.
// ***********************************************************************
#define PORTABLE
#define TIZEN
#define NUNIT_FRAMEWORK
#define NUNITLITE
#define NET_4_5
#define PARALLEL
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using NUnit.Compatibility;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Builders;
namespace NUnit.Framework
{
///
/// TestCaseSourceAttribute indicates the source to be used to
/// provide test fixture instances for a test class.
///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public class TestFixtureSourceAttribute : NUnitAttribute, IFixtureBuilder
{
private readonly NUnitTestFixtureBuilder _builder = new NUnitTestFixtureBuilder();
///
/// Error message string is public so the tests can use it
///
public const string MUST_BE_STATIC = "The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method.";
#region Constructors
///
/// Construct with the name of the method, property or field that will provide data
///
/// The name of a static method, property or field that will provide data.
public TestFixtureSourceAttribute(string sourceName)
{
this.SourceName = sourceName;
}
///
/// Construct with a Type and name
///
/// The Type that will provide data
/// The name of a static method, property or field that will provide data.
public TestFixtureSourceAttribute(Type sourceType, string sourceName)
{
this.SourceType = sourceType;
this.SourceName = sourceName;
}
///
/// Construct with a Type
///
/// The type that will provide data
public TestFixtureSourceAttribute(Type sourceType)
{
this.SourceType = sourceType;
}
#endregion
#region Properties
///
/// The name of a the method, property or fiend to be used as a source
///
public string SourceName { get; private set; }
///
/// A Type to be used as a source
///
public Type SourceType { get; private set; }
///
/// Gets or sets the category associated with every fixture created from
/// this attribute. May be a single category or a comma-separated list.
///
public string Category { get; set; }
#endregion
#region IFixtureBuilder Members
///
/// Construct one or more TestFixtures from a given Type,
/// using available parameter data.
///
/// The TypeInfo for which fixures are to be constructed.
/// One or more TestFixtures as TestSuite
public IEnumerable BuildFrom(ITypeInfo typeInfo)
{
Type sourceType = SourceType ?? typeInfo.Type;
foreach (TestFixtureParameters parms in GetParametersFor(sourceType))
yield return _builder.BuildFrom(typeInfo, parms);
}
#endregion
#region Helper Methods
///
/// Returns a set of ITestFixtureData items for use as arguments
/// to a parameterized test fixture.
///
/// The type for which data is needed.
///
public IEnumerable GetParametersFor(Type sourceType)
{
List data = new List();
try
{
IEnumerable source = GetTestFixtureSource(sourceType);
if (source != null)
{
foreach (object item in source)
{
var parms = item as ITestFixtureData;
if (parms == null)
{
object[] args = item as object[];
if (args == null)
{
args = new object[] { item };
}
parms = new TestFixtureParameters(args);
}
if (this.Category != null)
foreach (string cat in this.Category.Split(new char[] { ',' }))
parms.Properties.Add(PropertyNames.Category, cat);
data.Add(parms);
}
}
}
catch (Exception ex)
{
data.Clear();
data.Add(new TestFixtureParameters(ex));
}
return data;
}
private IEnumerable GetTestFixtureSource(Type sourceType)
{
// Handle Type implementing IEnumerable separately
if (SourceName == null)
return Reflect.Construct(sourceType) as IEnumerable;
MemberInfo[] members = sourceType.GetMember(SourceName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
if (members.Length == 1)
{
MemberInfo member = members[0];
var field = member as FieldInfo;
if (field != null)
return field.IsStatic
? (IEnumerable)field.GetValue(null)
: SourceMustBeStaticError();
var property = member as PropertyInfo;
if (property != null)
return property.GetGetMethod(true).IsStatic
? (IEnumerable)property.GetValue(null, null)
: SourceMustBeStaticError();
var m = member as MethodInfo;
if (m != null)
return m.IsStatic
? (IEnumerable)m.Invoke(null, null)
: SourceMustBeStaticError();
}
return null;
}
private static IEnumerable SourceMustBeStaticError()
{
var parms = new TestFixtureParameters();
parms.RunState = RunState.NotRunnable;
parms.Properties.Set(PropertyNames.SkipReason, MUST_BE_STATIC);
return new TestFixtureParameters[] { parms };
}
#endregion
}
}