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

NH-4052 - Collect schema validation exceptions #663

merged 1 commit into from
Sep 6, 2017

Conversation

DMDTT
Copy link

@DMDTT DMDTT commented Jul 14, 2017

NH-4052 - Collect schema validation exceptions

  • add list of exceptions to HibernateException
  • create HibernateException on validation fail and add to the exception list
  • return list of exceptions to throw one common HibernateException to be able to evaluate it on application side

Copy link
Member

@fredericDelaporte fredericDelaporte left a comment

Choose a reason for hiding this comment

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

Please fix the tests. One probably needs to be updated, the other seems to point a bug in your changes.

Your commit message has to be more descriptive. Including the Jira ticket is not enough, you should tell about what is it.

NH-4052 - aggregate schema validation exception

Would be better.

But overall this changes does not look to me as truly a valid AggregateException pattern. Here, the listed exceptions will not have been thrown and will not have any stack-trace. They should not be handled as exception, but as a simple list of string error messages. There is no value in listing exceptions having not been thrown and only carrying their message as significant data. Better just consolidate all their messages in one string.

throw new HibernateException(string.Format("Missing column: {0} in {1}", column.Name,
dialect.Qualify(tableInfo.Catalog, tableInfo.Schema, tableInfo.Name)));
exceptions.Add(new HibernateException(string.Format("Missing column: {0} in {1}", column.Name,
dialect.Qualify(tableInfo.Catalog, tableInfo.Schema, tableInfo.Name))));
Copy link
Member

Choose a reason for hiding this comment

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

Here lies a bug due to the change. A throw stops code execution, protecting in this case the code from reaching a null ref condition. You should make sure that everywhere you have replaced a throw by just an add in a list, the code following that will support the state for which an exception was supposed to be thrown or will be appropriately bypassed.

@@ -12,6 +13,7 @@ namespace NHibernate
[Serializable]
public class HibernateException : Exception
{
public List<HibernateException> Exceptions { get; }
Copy link
Member

Choose a reason for hiding this comment

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

Better follow usual conventions, like the one of the standard AggregateException: name this InnerExceptions, and expose this as a ReadOnlyCollection<Exception>.

@@ -12,6 +13,7 @@ namespace NHibernate
[Serializable]
public class HibernateException : Exception
Copy link
Member

Choose a reason for hiding this comment

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

I am not for adding this to the hibernate exception base class. If we add that, it should be on a specialized class, like adding class HibernateAggregateException : HibernateException.

@DMDTT
Copy link
Author

DMDTT commented Jul 17, 2017

@fredericDelaporte Thanks for your review.
Keeping the validation errors as a readonlycollection seems a more apropriate way then keeping one string.

I updated the code

Copy link
Member

@fredericDelaporte fredericDelaporte left a comment

Choose a reason for hiding this comment

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

This new design overall seems good for me.

Some undue changes needs to be reverted.

Modified asserts should be modernized.

A new test have to be added in SchemaValidateFixture for testing the new feature. It should ascertain that in case of many errors, they are all listed.

For the new class, better use the less specialized interface for its constructor arguments.

Please add xml comments on new public classes (SchemaValidationException).

@@ -7,7 +7,7 @@
</configSections>

<connectionStrings>
<add name="TestConnectionString" connectionString="Server=localhost\sqlexpress;Database=nhibernate;Integrated Security=SSPI" />
<add name="TestConnectionString" connectionString="Server=localhost;Database=nhibernate;Integrated Security=SSPI" />
Copy link
Member

Choose a reason for hiding this comment

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

Please revert. You should not need to change that. Use ShowBuildMenu and setup your test configuration with it.

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
Copy link
Member

Choose a reason for hiding this comment

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

Change now unneeded, please revert too.

@@ -9,7 +9,7 @@
<session-factory name="NHibernate.TestDatabaseSetup">
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string">
Server=.\SQLExpress;initial catalog=master;Integrated Security=SSPI
Server=localhost;initial catalog=master;Integrated Security=SSPI
Copy link
Member

Choose a reason for hiding this comment

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

Please revert too.

@@ -7,6 +7,7 @@
using NHibernate.Criterion;
using NHibernate.Engine;
using NHibernate.Tool.hbm2ddl;
using NHibernate.Util;
Copy link
Member

Choose a reason for hiding this comment

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

We wish to remove NHibernate collection custom extensions, so please do not add more usages of them.

{
Assert.IsTrue(he.Message.Contains("Home_Validate"));
Assert.IsTrue(e.Message.Contains("Schema validation failed: see list of validation errors"));
Assert.IsTrue(e.ValidationErrors.Contains("Missing table: Home_Validate"));
Copy link
Member

Choose a reason for hiding this comment

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

Better use Fluent syntax: Assert.That. NUnit does no more add features to the others, and may obsolete them.
By the way, just having "expected true but was false" as an error message while there is more than one test on true is not practical : better at least add an explicit error message.

Here the whole thing could be simplified too:

Assert.That(() => validator.Validate(),
    Throws.TypeOf<SchemaValidationException>()
        .And.Property("ValidationErrors").Contain("Missing table: Home_Validate"));

(Checking the type and the error list without checking the exception message seems enough to me, the type is already sufficiently specialized.)

{
Assert.That(e.Message, Does.StartWith("Missing column: Name"));
Assert.That(e.Message, Does.StartWith("Schema validation failed: see list of validation errors"));
Assert.That(e.ValidationErrors[0], Does.StartWith("Missing column: Name"));
Copy link
Member

Choose a reason for hiding this comment

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

Better but could be simplified as previous assert.

@fredericDelaporte fredericDelaporte changed the title NH-4052 NH-4052 - Collect schema validation exceptions Jul 18, 2017
@hazzik hazzik modified the milestone: 5.1 Aug 3, 2017
@hazzik
Copy link
Member

hazzik commented Sep 6, 2017

Mentioned issues resolved. Squashed, rebased and Async tests regenerated.

@hazzik
Copy link
Member

hazzik commented Sep 6, 2017

Ok, I've forgot to add a new test for the feature.

Copy link
Member

@fredericDelaporte fredericDelaporte left a comment

Choose a reason for hiding this comment

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

I may finish that if you are not already on it.

() => validatorV2.ValidateAsync(),
Throws.TypeOf<SchemaValidationException>()
.And.Message.EqualTo("Schema validation failed: see list of validation errors")
.And.Property("ValidationErrors").Contains("Missing column: Name in nhibernate.dbo.Version"));
Copy link
Member

Choose a reason for hiding this comment

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

As showcased by failing tests, this column naming is specific to SQL Server and causes the test to fail for other db.

@hazzik
Copy link
Member

hazzik commented Sep 6, 2017 via email

+ add SchemaValidationException
+ keep list of validation messages and throw new SchemaValidationException
+ adjust/ fix unittests
Copy link
Member

@fredericDelaporte fredericDelaporte left a comment

Choose a reason for hiding this comment

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

Rebased by the way, test added.

- 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.

<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.

</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.

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);
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.

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);

@hazzik hazzik modified the milestones: 5.1, 5.0 Sep 6, 2017
@fredericDelaporte fredericDelaporte merged commit 8d0f102 into nhibernate:master Sep 6, 2017
@DMDTT
Copy link
Author

DMDTT commented Sep 7, 2017

@fredericDelaporte @hazzik
Thanks for your work guys,
I didn't manage it to work on it in the last month, sry for that.

But nethertheless the work of yours is great. Thanks again.

fredericDelaporte added a commit to fredericDelaporte/nhibernate-core that referenced this pull request Nov 26, 2017
 * NH-4052 (nhibernate#663) has introduced a new exception class, but has forgotten to provide its serializable implementation.
hazzik pushed a commit to fredericDelaporte/nhibernate-core that referenced this pull request Nov 26, 2017
 * NH-4052 (nhibernate#663) has introduced a new exception class, but has forgotten to provide its serializable implementation.
hazzik pushed a commit that referenced this pull request Nov 27, 2017
- NH-4052 (#663) has introduced a new exception class but has forgotten to provide its serializable implementation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants