Skip to content

NH-4052 - Collect schema validation exceptions #663

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/AsyncGenerator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@
applyChanges: true
analyzation:
methodConversion:
- conversion: Copy
hasAttributeName: OneTimeSetUpAttribute
- conversion: Copy
hasAttributeName: OneTimeTearDownAttribute
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was converting them to async otherwise, causing them to be invalid. The test for this feature does not inherit a base test class, and was not cleaning up correctly (leaving schema). So I have added setup and teardown logic in it.

- conversion: Copy
hasAttributeName: SetUpAttribute
- conversion: Copy
hasAttributeName: TearDownAttribute
- conversion: Smart
hasAttributeName: TestAttribute
- conversion: Smart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,16 @@ public async Task SchemaExport_Export_CreatesExportScriptAsync()
}

[Test]
public async Task SchemaExport_Validate_CausesValidateExceptionAsync()
public void SchemaExport_Validate_CausesValidateExceptionAsync()
{
Configuration configuration = GetConfiguration();
SchemaValidator validator = new SchemaValidator(configuration);
try
{
await (validator.ValidateAsync());
}
catch (HibernateException he)
{
Assert.IsTrue(he.Message.Contains("Home_Validate"));
return;
}
throw new Exception("Should not get to this exception");

Assert.That(
() => validator.ValidateAsync(),
Throws.TypeOf<SchemaValidationException>()
.And.Message.EqualTo("Schema validation failed: see list of validation errors")
.And.Property("ValidationErrors").Contains("Missing table: Home_Validate"));
}

private Configuration GetConfiguration()
Expand Down Expand Up @@ -132,4 +128,4 @@ protected IList Mappings
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,44 @@ namespace NHibernate.Test.Tools.hbm2ddl.SchemaValidator
[TestFixture]
public class SchemaValidateFixtureAsync
{
[Test]
public async Task ShouldVerifySameTableAsync()
private const string _resourcesPrefix = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.";
private const string _version1Resource = _resourcesPrefix + "1_Version.hbm.xml";
private const string _version2Resource = _resourcesPrefix + "2_Version.hbm.xml";
private const string _version3Resource = _resourcesPrefix + "3_Version.hbm.xml";
private Configuration _configuration1;
private SchemaExport _export1;

[OneTimeSetUp]
public void OneTimeSetUp()
{
_configuration1 = BuildConfiguration(_version1Resource);
}

[SetUp]
public void SetUp()
{
const string resource = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.1_Version.hbm.xml";
var cfg = BuildConfiguration(resource);
_export1 = new SchemaExport(_configuration1);
_export1.Create(true, true);
}

await (new SchemaExport(cfg).ExecuteAsync(true, true, false));
[TearDown]
public void TearDown()
{
_export1.Drop(true, true);
}

var validator = new Tool.hbm2ddl.SchemaValidator((cfg));
await (validator.ValidateAsync());
[Test]
public Task ShouldVerifySameTableAsync()
{
try
{
var validator = new Tool.hbm2ddl.SchemaValidator((_configuration1));
return validator.ValidateAsync();
}
catch (System.Exception ex)
{
return Task.FromException<object>(ex);
}
}

[Test, SetCulture("tr-TR"), SetUICulture("tr-TR")]
Expand All @@ -45,36 +73,49 @@ public async Task ShouldVerifySameTableTurkishAsync()
var v = new Version();
Assert.That(v.Id, Is.TypeOf<int>());

var cfg = BuildConfiguration(_version1Resource);

const string resource = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.1_Version.hbm.xml";
var cfg = BuildConfiguration(resource);
var export = new SchemaExport(cfg);
await (export.CreateAsync(true, true));
try
{
var validator = new Tool.hbm2ddl.SchemaValidator(cfg);
await (validator.ValidateAsync());
}
finally
{
await (export.DropAsync(true, true));
}
}

await (new SchemaExport(cfg).ExecuteAsync(true, true, false));
[Test]
public void ShouldNotVerifyModifiedTableAsync()
{
var cfgV2 = BuildConfiguration(_version2Resource);
var validatorV2 = new Tool.hbm2ddl.SchemaValidator(cfgV2);

var validator = new Tool.hbm2ddl.SchemaValidator(cfg);
await (validator.ValidateAsync());
Assert.That(
() => validatorV2.ValidateAsync(),
Throws.TypeOf<SchemaValidationException>()
.And.Message.EqualTo("Schema validation failed: see list of validation errors")
.And.Property("ValidationErrors").Some.Contains("Missing column: Name in ").IgnoreCase.And.Contains("Version").IgnoreCase);
}

[Test]
public async Task ShouldNotVerifyModifiedTableAsync()
public void ShouldNotVerifyMultiModifiedTableAsync()
{
const string resource1 = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.1_Version.hbm.xml";
var cfgV1 = BuildConfiguration(resource1);
var cfg = BuildConfiguration(_version3Resource);

const string resource2 = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.2_Version.hbm.xml";
var cfgV2 = BuildConfiguration(resource2);

await (new SchemaExport(cfgV1).ExecuteAsync(true, true, false));
var validator = new Tool.hbm2ddl.SchemaValidator(cfg);

var validatorV2 = new Tool.hbm2ddl.SchemaValidator(cfgV2);
try
{
await (validatorV2.ValidateAsync());
}
catch (HibernateException e)
{
Assert.That(e.Message, Does.StartWith("Missing column: Name"));
}
var error = Assert.ThrowsAsync<SchemaValidationException>(() => validator.ValidateAsync());
Assert.That(error,
Has.Message.EqualTo("Schema validation failed: see list of validation errors")
.And.Property("ValidationErrors").Some.Contains("Missing column: Name in ").IgnoreCase.And.Contains("Version").IgnoreCase);
Assert.That(error,
Has.Property("ValidationErrors").Some.Contains("Missing column: Title in ").IgnoreCase.And.Contains("Version").IgnoreCase);
Assert.That(error,
Has.Property("ValidationErrors").Some.Contains("Missing sequence or table: ").IgnoreCase.And.Contains("id_table").IgnoreCase);
}

private static Configuration BuildConfiguration(string resource)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,12 @@ public void SchemaExport_Validate_CausesValidateException()
{
Configuration configuration = GetConfiguration();
SchemaValidator validator = new SchemaValidator(configuration);
try
{
validator.Validate();
}
catch (HibernateException he)
{
Assert.IsTrue(he.Message.Contains("Home_Validate"));
return;
}
throw new Exception("Should not get to this exception");

Assert.That(
() => validator.Validate(),
Throws.TypeOf<SchemaValidationException>()
.And.Message.EqualTo("Schema validation failed: see list of validation errors")
.And.Property("ValidationErrors").Contains("Missing table: Home_Validate"));
}

private Configuration GetConfiguration()
Expand Down Expand Up @@ -133,4 +129,4 @@ protected IList Mappings
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="NHibernate.Test.Tools.hbm2ddl.SchemaValidator"
assembly="NHibernate.Test">

<class name="Version">
<id name="Id">
<generator class="NHibernate.Id.TableHiLoGenerator">
<param name="table">id_table</param>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Altered table name for generator.

<param name="column">next_hi_value_column</param>
</generator>
</id>
<property name="Description"/>
<property name="Name"/>
<property name="Title"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more missing column.

</class>
</hibernate-mapping>
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,36 @@ namespace NHibernate.Test.Tools.hbm2ddl.SchemaValidator
[TestFixture]
public class SchemaValidateFixture
{
[Test]
public void ShouldVerifySameTable()
private const string _resourcesPrefix = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.";
private const string _version1Resource = _resourcesPrefix + "1_Version.hbm.xml";
private const string _version2Resource = _resourcesPrefix + "2_Version.hbm.xml";
private const string _version3Resource = _resourcesPrefix + "3_Version.hbm.xml";
private Configuration _configuration1;
private SchemaExport _export1;

[OneTimeSetUp]
public void OneTimeSetUp()
{
const string resource = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.1_Version.hbm.xml";
var cfg = BuildConfiguration(resource);
_configuration1 = BuildConfiguration(_version1Resource);
}

new SchemaExport(cfg).Execute(true, true, false);
[SetUp]
public void SetUp()
{
_export1 = new SchemaExport(_configuration1);
_export1.Create(true, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a wrapper more explicit than Execute(true, true, false).

}

[TearDown]
public void TearDown()
{
_export1.Drop(true, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was not dropping previously.

}

var validator = new Tool.hbm2ddl.SchemaValidator((cfg));
[Test]
public void ShouldVerifySameTable()
{
var validator = new Tool.hbm2ddl.SchemaValidator((_configuration1));
validator.Validate();
}

Expand All @@ -34,36 +55,49 @@ public void ShouldVerifySameTableTurkish()
var v = new Version();
Assert.That(v.Id, Is.TypeOf<int>());

var cfg = BuildConfiguration(_version1Resource);

const string resource = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.1_Version.hbm.xml";
var cfg = BuildConfiguration(resource);

new SchemaExport(cfg).Execute(true, true, false);

var validator = new Tool.hbm2ddl.SchemaValidator(cfg);
validator.Validate();
var export = new SchemaExport(cfg);
export.Create(true, true);
Copy link
Member

@fredericDelaporte fredericDelaporte Sep 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the Turkish case, I am not sure if creating the schema under the Turkish culture is required or not, so I have left it in place.

try
{
var validator = new Tool.hbm2ddl.SchemaValidator(cfg);
validator.Validate();
}
finally
{
export.Drop(true, true);
}
}

[Test]
public void ShouldNotVerifyModifiedTable()
{
const string resource1 = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.1_Version.hbm.xml";
var cfgV1 = BuildConfiguration(resource1);
var cfgV2 = BuildConfiguration(_version2Resource);
var validatorV2 = new Tool.hbm2ddl.SchemaValidator(cfgV2);

Assert.That(
() => validatorV2.Validate(),
Throws.TypeOf<SchemaValidationException>()
.And.Message.EqualTo("Schema validation failed: see list of validation errors")
.And.Property("ValidationErrors").Some.Contains("Missing column: Name in ").IgnoreCase.And.Contains("Version").IgnoreCase);
}

const string resource2 = "NHibernate.Test.Tools.hbm2ddl.SchemaValidator.2_Version.hbm.xml";
var cfgV2 = BuildConfiguration(resource2);
[Test]
public void ShouldNotVerifyMultiModifiedTable()
{
var cfg = BuildConfiguration(_version3Resource);

new SchemaExport(cfgV1).Execute(true, true, false);
var validator = new Tool.hbm2ddl.SchemaValidator(cfg);

var validatorV2 = new Tool.hbm2ddl.SchemaValidator(cfgV2);
try
{
validatorV2.Validate();
}
catch (HibernateException e)
{
Assert.That(e.Message, Does.StartWith("Missing column: Name"));
}
var error = Assert.Throws<SchemaValidationException>(() => validator.Validate());
Assert.That(error,
Has.Message.EqualTo("Schema validation failed: see list of validation errors")
.And.Property("ValidationErrors").Some.Contains("Missing column: Name in ").IgnoreCase.And.Contains("Version").IgnoreCase);
Copy link
Member

@fredericDelaporte fredericDelaporte Sep 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know another way for testing multiple values.
Following code is:

Assert.That(error,
 	Has.Property("ValidationErrors").Some.Contains("Missing column: Title in ").IgnoreCase.And.Contains("Version").IgnoreCase);
Assert.That(error,
	Has.Property("ValidationErrors").Some.Contains("Missing sequence or table: ").IgnoreCase.And.Contains("id_table").IgnoreCase);

Assert.That(error,
Has.Property("ValidationErrors").Some.Contains("Missing column: Title in ").IgnoreCase.And.Contains("Version").IgnoreCase);
Assert.That(error,
Has.Property("ValidationErrors").Some.Contains("Missing sequence or table: ").IgnoreCase.And.Contains("id_table").IgnoreCase);
}

private static Configuration BuildConfiguration(string resource)
Expand Down
6 changes: 6 additions & 0 deletions src/NHibernate.Test/Tools/hbm2ddl/SchemaValidator/Version.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class Version
private int id;
private string name;
private string description;
private string title;
private Version previous;

public virtual int Id
Expand All @@ -29,6 +30,11 @@ public virtual string Description
set { description = value; }
}

public virtual string Title
{
get { return title; }
set { title = value; }
}

public virtual Version Previous
{
Expand Down
16 changes: 13 additions & 3 deletions src/NHibernate/Cfg/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2404,6 +2404,7 @@ public void ValidateSchema(Dialect.Dialect dialect, IDatabaseMetadata databaseMe
string defaultCatalog = PropertiesHelper.GetString(Environment.DefaultCatalog, properties, null);
string defaultSchema = PropertiesHelper.GetString(Environment.DefaultSchema, properties, null);

var validationErrors = new List<string>();
var iter = TableMappings;
foreach (var table in iter)
{
Expand All @@ -2421,9 +2422,13 @@ public void ValidateSchema(Dialect.Dialect dialect, IDatabaseMetadata databaseMe
table.Catalog ?? defaultCatalog,
table.IsQuoted);
if (tableInfo == null)
throw new HibernateException("Missing table: " + table.Name);
{
validationErrors.Add("Missing table: " + table.Name);
}
else
table.ValidateColumns(dialect, mapping, tableInfo);
{
validationErrors.AddRange(table.ValidateColumns(dialect, mapping, tableInfo));
}
}
}

Expand All @@ -2433,9 +2438,14 @@ public void ValidateSchema(Dialect.Dialect dialect, IDatabaseMetadata databaseMe
string key = generator.GeneratorKey();
if (!databaseMetadata.IsSequence(key) && !databaseMetadata.IsTable(key))
{
throw new HibernateException(string.Format("Missing sequence or table: " + key));
validationErrors.Add("Missing sequence or table: " + key);
}
}

if (validationErrors.Count > 0)
{
throw new SchemaValidationException("Schema validation failed: see list of validation errors", validationErrors);
}
}

private IEnumerable<IPersistentIdentifierGenerator> IterateGenerators(Dialect.Dialect dialect)
Expand Down
Loading