// 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;
///
/// 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.
///
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; }
}
///
/// 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.
///
/// A func to create the context.
protected static void EnsureDatabaseInitialized(Func createContext)
{
using (var context = createContext())
{
context.Database.Initialize(force: false);
}
}
///
/// Drops the database that would be used for the context. Usually used to avoid errors during initialization.
///
/// A func to create the context.
protected static void DropDatabase(Func createContext)
{
using (var context = createContext())
{
context.Database.Delete();
}
}
///
/// Drops and then initializes the database that will be used for the context.
///
/// A func to create the context.
protected static void ResetDatabase(Func createContext)
{
DropDatabase(createContext);
EnsureDatabaseInitialized(createContext);
}
///
/// Initializes the metadata files and creates databases for existing CSDL/EDMX files.
///
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());
context.Database.Initialize(force: false);
}
}
private static bool _metadataForSimpleModelCreated;
///
/// Creates the metadata files (CSDL/SSDL/MSL) for the SimpleModelContext.
///
protected static void CreateMetadataFilesForSimpleModel()
{
if (!_metadataForSimpleModelCreated)
{
var builder = SimpleModelContext.CreateBuilder();
ModelHelpers.WriteMetadataFiles(builder, @".\SimpleModel");
using (var connection = SimpleConnection())
{
new SimpleModelContext(connection, builder.Build(connection).Compile()).Database.Initialize(false);
}
_metadataForSimpleModelCreated = true;
}
}
private static string _simpleModelEntityConnectionString;
///
/// An entity connection string for the SimpleModelContext.
///
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()));
}
}
#endregion
#region Construction helpers
protected static TContext CreateContext(
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();
}
else if (providerName == "System.Data.SqlServerCe.4.0")
{
connection = SimpleCeConnection();
}
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();
}
else if (providerName == "System.Data.SqlServerCe.4.0")
{
connectionString = SimpleCeConnectionString();
}
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(
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();
break;
case DbCompiledModelContents.IsSuperset:
builder.Entity();
builder.Entity();
builder.Entity();
break;
case DbCompiledModelContents.Match:
builder.Entity();
builder.Entity();
break;
case DbCompiledModelContents.DontMatch:
builder.Entity();
builder.Entity();
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().IsNotInModel();
context.Assert().IsNotInModel();
break;
case DbCompiledModelContents.IsSubset:
Assert.NotNull(context.Categories);
Assert.NotNull(context.Products);
context.Assert().IsInModel();
context.Assert().IsInModel(); // reachability
break;
case DbCompiledModelContents.IsSuperset:
Assert.NotNull(context.Categories);
Assert.NotNull(context.Products);
context.Assert().IsInModel();
context.Assert().IsInModel();
context.Assert().IsInModel();
break;
case DbCompiledModelContents.Match:
Assert.NotNull(context.Categories);
Assert.NotNull(context.Products);
context.Assert().IsInModel();
context.Assert().IsInModel();
context.Assert().IsNotInModel();
break;
case DbCompiledModelContents.DontMatch:
Assert.NotNull(context.Categories);
Assert.NotNull(context.Products);
context.Assert().IsInModel();
context.Assert().IsInModel();
break;
default:
throw new ArgumentException("Invalid DbCompiledModelContents Arguments passed in, " + contents);
}
}
}
#endregion
}
}