324 lines
14 KiB
C#
324 lines
14 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
namespace System.Data.Entity
|
|
{
|
|
using System.Data.Common;
|
|
using System.Data.Entity.Infrastructure;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using FunctionalTests.ProductivityApi.TemplateModels.CsAdvancedPatterns;
|
|
using FunctionalTests.ProductivityApi.TemplateModels.CsMonsterModel;
|
|
using ProductivityApiTests;
|
|
using SimpleModel;
|
|
using Xunit;
|
|
|
|
/// <summary>
|
|
/// Base class for Productivity API tests that sets up a simple model and some data.
|
|
/// Call ClassInitializeBase from the ClassInitialize method of your test class to ensure
|
|
/// that the test data is configured.
|
|
/// </summary>
|
|
public class FunctionalTestBase : TestBase
|
|
{
|
|
#region Test database setup
|
|
|
|
protected int AdvancedModelOfficeCount
|
|
{
|
|
get { return 4; }
|
|
}
|
|
|
|
protected int AdvancedModelBuildingCount
|
|
{
|
|
get { return 2; }
|
|
}
|
|
|
|
protected int AdvancedModelWhiteboardCount
|
|
{
|
|
get { return 3; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ensures the database for the context is created and seeded. This is typically used
|
|
/// when a test is going to use a transaction to ensure that the DDL happens outside of
|
|
/// the transaction.
|
|
/// </summary>
|
|
/// <param name="createContext"> A func to create the context. </param>
|
|
protected static void EnsureDatabaseInitialized(Func<DbContext> createContext)
|
|
{
|
|
using (var context = createContext())
|
|
{
|
|
context.Database.Initialize(force: false);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Drops the database that would be used for the context. Usually used to avoid errors during initialization.
|
|
/// </summary>
|
|
/// <param name="createContext"> A func to create the context. </param>
|
|
protected static void DropDatabase(Func<DbContext> createContext)
|
|
{
|
|
using (var context = createContext())
|
|
{
|
|
context.Database.Delete();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Drops and then initializes the database that will be used for the context.
|
|
/// </summary>
|
|
/// <param name="createContext"> A func to create the context. </param>
|
|
protected static void ResetDatabase(Func<DbContext> createContext)
|
|
{
|
|
DropDatabase(createContext);
|
|
EnsureDatabaseInitialized(createContext);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes the metadata files and creates databases for existing CSDL/EDMX files.
|
|
/// </summary>
|
|
protected static void InitializeModelFirstDatabases()
|
|
{
|
|
const string prefix = "FunctionalTests.ProductivityApi.TemplateModels.Schemas.";
|
|
ResourceUtilities.CopyEmbeddedResourcesToCurrentDir(
|
|
typeof(TemplateTests).Assembly,
|
|
prefix,
|
|
/*overwrite*/ true,
|
|
"AdvancedPatterns.edmx",
|
|
"MonsterModel.csdl",
|
|
"MonsterModel.msl",
|
|
"MonsterModel.ssdl");
|
|
|
|
// Extract the csdl, msl, and ssdl from the edmx so that they can be referenced in the connection string.
|
|
ModelHelpers.WriteMetadataFiles(File.ReadAllText(@".\AdvancedPatterns.edmx"), @".\AdvancedPatterns");
|
|
|
|
using (var context = new AdvancedPatternsModelFirstContext())
|
|
{
|
|
context.Database.Initialize(force: false);
|
|
}
|
|
|
|
using (var context = new MonsterModel())
|
|
{
|
|
Database.SetInitializer(new DropCreateDatabaseAlways<MonsterModel>());
|
|
context.Database.Initialize(force: false);
|
|
}
|
|
}
|
|
|
|
private static bool _metadataForSimpleModelCreated;
|
|
|
|
/// <summary>
|
|
/// Creates the metadata files (CSDL/SSDL/MSL) for the SimpleModelContext.
|
|
/// </summary>
|
|
protected static void CreateMetadataFilesForSimpleModel()
|
|
{
|
|
if (!_metadataForSimpleModelCreated)
|
|
{
|
|
var builder = SimpleModelContext.CreateBuilder();
|
|
ModelHelpers.WriteMetadataFiles(builder, @".\SimpleModel");
|
|
|
|
using (var connection = SimpleConnection<SimpleModelContext>())
|
|
{
|
|
new SimpleModelContext(connection, builder.Build(connection).Compile()).Database.Initialize(false);
|
|
}
|
|
|
|
_metadataForSimpleModelCreated = true;
|
|
}
|
|
}
|
|
|
|
private static string _simpleModelEntityConnectionString;
|
|
|
|
/// <summary>
|
|
/// An entity connection string for the SimpleModelContext.
|
|
/// </summary>
|
|
protected static string SimpleModelEntityConnectionString
|
|
{
|
|
get
|
|
{
|
|
const string baseConnectionString =
|
|
@"metadata=.\SimpleModel.csdl|.\SimpleModel.ssdl|.\SimpleModel.msl;
|
|
provider=System.Data.SqlClient;provider connection string='{0}'";
|
|
return _simpleModelEntityConnectionString ??
|
|
(_simpleModelEntityConnectionString =
|
|
String.Format(
|
|
CultureInfo.InvariantCulture, baseConnectionString,
|
|
SimpleConnectionString<SimpleModelContext>()));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Construction helpers
|
|
|
|
protected static TContext CreateContext<TContext>(
|
|
DbContextConstructorArgumentType arguments,
|
|
string providerName = "System.Data.SqlClient")
|
|
where TContext : DbContext
|
|
{
|
|
DbConnection connection = null;
|
|
if (arguments == DbContextConstructorArgumentType.Connection
|
|
||
|
|
arguments == DbContextConstructorArgumentType.ConnectionAndDbCompiledModel)
|
|
{
|
|
if (providerName == "System.Data.SqlClient")
|
|
{
|
|
connection = SimpleConnection<TContext>();
|
|
}
|
|
else if (providerName == "System.Data.SqlServerCe.4.0")
|
|
{
|
|
connection = SimpleCeConnection<TContext>();
|
|
}
|
|
else
|
|
{
|
|
throw new ArgumentException("Invalid provider specified, " + providerName);
|
|
}
|
|
}
|
|
|
|
string connectionString = null;
|
|
if (arguments == DbContextConstructorArgumentType.ConnectionString
|
|
||
|
|
arguments == DbContextConstructorArgumentType.ConnectionStringAndDbCompiledModel)
|
|
{
|
|
if (providerName == "System.Data.SqlClient")
|
|
{
|
|
connectionString = SimpleConnectionString<TContext>();
|
|
}
|
|
else if (providerName == "System.Data.SqlServerCe.4.0")
|
|
{
|
|
connectionString = SimpleCeConnectionString<TContext>();
|
|
}
|
|
else
|
|
{
|
|
throw new ArgumentException("Invalid provider specified, " + providerName);
|
|
}
|
|
}
|
|
|
|
var providerInfo
|
|
= (providerName == "System.Data.SqlServerCe.4.0")
|
|
? ProviderRegistry.SqlCe4_ProviderInfo
|
|
: ProviderRegistry.Sql2008_ProviderInfo;
|
|
|
|
TContext context = null;
|
|
switch (arguments)
|
|
{
|
|
case DbContextConstructorArgumentType.Parameterless:
|
|
context = (TContext)Activator.CreateInstance(typeof(TContext));
|
|
break;
|
|
case DbContextConstructorArgumentType.DbCompiledModel:
|
|
context =
|
|
(TContext)
|
|
Activator.CreateInstance(
|
|
typeof(TContext),
|
|
SimpleModelContext.CreateBuilder().Build(providerInfo).Compile());
|
|
break;
|
|
case DbContextConstructorArgumentType.Connection:
|
|
context = (TContext)Activator.CreateInstance(typeof(TContext), connection, false);
|
|
break;
|
|
case DbContextConstructorArgumentType.ConnectionString:
|
|
context = (TContext)Activator.CreateInstance(typeof(TContext), connectionString);
|
|
break;
|
|
case DbContextConstructorArgumentType.ConnectionAndDbCompiledModel:
|
|
context =
|
|
(TContext)
|
|
Activator.CreateInstance(
|
|
typeof(TContext), connection,
|
|
SimpleModelContext.CreateBuilder().Build(connection).Compile(), false);
|
|
break;
|
|
case DbContextConstructorArgumentType.ConnectionStringAndDbCompiledModel:
|
|
context =
|
|
(TContext)
|
|
Activator.CreateInstance(
|
|
typeof(TContext), connectionString,
|
|
SimpleModelContext.CreateBuilder().Build(providerInfo).Compile());
|
|
break;
|
|
default:
|
|
throw new ArgumentException("Invalid DbContext constructor arguments " + arguments);
|
|
}
|
|
|
|
return context;
|
|
}
|
|
|
|
protected void VerifySetsAreInitialized<TContext>(
|
|
DbCompiledModelContents contents,
|
|
DbProviderInfo providerInfo = null)
|
|
where TContext : SimpleModelContextWithNoData
|
|
{
|
|
providerInfo = providerInfo ?? ProviderRegistry.Sql2008_ProviderInfo;
|
|
|
|
// Arrange
|
|
// DbCompiledModel creation as appropriate for the various model content options
|
|
var builder = new DbModelBuilder();
|
|
|
|
switch (contents)
|
|
{
|
|
case DbCompiledModelContents.IsEmpty:
|
|
// Do nothing as builder has already been initialized
|
|
break;
|
|
case DbCompiledModelContents.IsSubset:
|
|
// Product is not defined here
|
|
builder.Entity<Category>();
|
|
break;
|
|
case DbCompiledModelContents.IsSuperset:
|
|
builder.Entity<Category>();
|
|
builder.Entity<Product>();
|
|
builder.Entity<Login>();
|
|
break;
|
|
case DbCompiledModelContents.Match:
|
|
builder.Entity<Category>();
|
|
builder.Entity<Product>();
|
|
break;
|
|
case DbCompiledModelContents.DontMatch:
|
|
builder.Entity<FeaturedProduct>();
|
|
builder.Entity<Login>();
|
|
break;
|
|
default:
|
|
throw new ArgumentException("Invalid DbCompiledModelContents Arguments passed in, " + contents);
|
|
}
|
|
|
|
var model = builder.Build(providerInfo).Compile();
|
|
|
|
// Act
|
|
using (var context = (TContext)Activator.CreateInstance(typeof(TContext), model))
|
|
{
|
|
// Verification as appropriate for the various model content options
|
|
switch (contents)
|
|
{
|
|
case DbCompiledModelContents.IsEmpty:
|
|
Assert.NotNull(context.Categories);
|
|
Assert.NotNull(context.Products);
|
|
context.Assert<Category>().IsNotInModel();
|
|
context.Assert<Product>().IsNotInModel();
|
|
break;
|
|
case DbCompiledModelContents.IsSubset:
|
|
Assert.NotNull(context.Categories);
|
|
Assert.NotNull(context.Products);
|
|
context.Assert<Category>().IsInModel();
|
|
context.Assert<Product>().IsInModel(); // reachability
|
|
break;
|
|
case DbCompiledModelContents.IsSuperset:
|
|
Assert.NotNull(context.Categories);
|
|
Assert.NotNull(context.Products);
|
|
context.Assert<Category>().IsInModel();
|
|
context.Assert<Product>().IsInModel();
|
|
context.Assert<Login>().IsInModel();
|
|
break;
|
|
case DbCompiledModelContents.Match:
|
|
Assert.NotNull(context.Categories);
|
|
Assert.NotNull(context.Products);
|
|
context.Assert<Category>().IsInModel();
|
|
context.Assert<Product>().IsInModel();
|
|
context.Assert<Login>().IsNotInModel();
|
|
break;
|
|
case DbCompiledModelContents.DontMatch:
|
|
Assert.NotNull(context.Categories);
|
|
Assert.NotNull(context.Products);
|
|
context.Assert<Login>().IsInModel();
|
|
context.Assert<FeaturedProduct>().IsInModel();
|
|
break;
|
|
default:
|
|
throw new ArgumentException("Invalid DbCompiledModelContents Arguments passed in, " + contents);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|