Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

* Imported source from ShadeTree.

* Renamed project files and assembly output names.
* Imported ExampleAttribute.cs from StoryTeller project and removed the reference to it, as this was the only thing used from it.
* Converted dependency on ShadeTree.Core to an assembly reference and added that to the tools.
* Added first attempt at a logo

git-svn-id: https://fluent-nhibernate.googlecode.com/svn/trunk@2 48f0ce17-cc52-0410-af8c-857c09b6549b
  • Loading branch information...
commit 58a58a496ebf3e1267429fb73a282406dc36af9d 1 parent 4002c69
@jagregory authored
Showing with 103,328 additions and 0 deletions.
  1. BIN  docs/logo.png
  2. +21 −0 src/CommonAssemblyInfo.cs
  3. +14 −0 src/FluentNHibernate.Testing/Debugging.cs
  4. +213 −0 src/FluentNHibernate.Testing/DeclarativeTesting.htm
  5. +278 −0 src/FluentNHibernate.Testing/DomainModel/ConnectedTester.cs
  6. +92 −0 src/FluentNHibernate.Testing/DomainModel/EntityEquality.cs
  7. +24 −0 src/FluentNHibernate.Testing/DomainModel/Generation/CodeFileSmokeTester.cs
  8. +85 −0 src/FluentNHibernate.Testing/DomainModel/InMemoryRepositoryTester.cs
  9. +390 −0 src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapXmlCreationTester.cs
  10. +94 −0 src/FluentNHibernate.Testing/DomainModel/Mapping/ConventionsTester.cs
  11. +33 −0 src/FluentNHibernate.Testing/DomainModel/Mapping/PropertyMapTester.cs
  12. +179 −0 src/FluentNHibernate.Testing/DomainModel/Query/EntityQueryDefinitionTester.cs
  13. +29 −0 src/FluentNHibernate.Testing/DomainModel/Query/FilterTypeRegistryTester.cs
  14. +61 −0 src/FluentNHibernate.Testing/DomainModel/Query/FilterTypeTester.cs
  15. +127 −0 src/FluentNHibernate.Testing/Fixtures.cs
  16. +109 −0 src/FluentNHibernate.Testing/FluentNHibernate.Testing.csproj
  17. +8 −0 src/FluentNHibernate.Testing/Properties/AssemblyInfo.cs
  18. +205 −0 src/FluentNHibernate.Testing/SpecificationExtensions.cs
  19. +18 −0 src/FluentNHibernate.Testing/TestUtility.cs
  20. +25 −0 src/FluentNHibernate.sln
  21. +9 −0 src/FluentNHibernate/AssemblyInfo.cs
  22. +96 −0 src/FluentNHibernate/Conventions.cs
  23. +41 −0 src/FluentNHibernate/Entity.cs
  24. +154 −0 src/FluentNHibernate/Fixtures/DomainClassFixture.cs
  25. +59 −0 src/FluentNHibernate/Fixtures/DomainFixtureWatcher.cs
  26. +60 −0 src/FluentNHibernate/Fixtures/DomainListFixture.cs
  27. +70 −0 src/FluentNHibernate/Fixtures/DomainObjectFinder.cs
  28. +33 −0 src/FluentNHibernate/Fixtures/ExampleAttribute.cs
  29. +19 −0 src/FluentNHibernate/Fixtures/TestContext.cs
  30. +132 −0 src/FluentNHibernate/FluentNHibernate.csproj
  31. +170 −0 src/FluentNHibernate/Generation/CodeFile.cs
  32. +85 −0 src/FluentNHibernate/Generation/DomainFixture.cs
  33. +58 −0 src/FluentNHibernate/Generation/DomainProperty.cs
  34. +83 −0 src/FluentNHibernate/Generation/GenericSimpleProperty.cs
  35. +35 −0 src/FluentNHibernate/Generation/IProperty.cs
  36. +89 −0 src/FluentNHibernate/Generation/PropertyBuilder.cs
  37. +63 −0 src/FluentNHibernate/Generation/SimpleProperty.cs
  38. +16 −0 src/FluentNHibernate/IMappingVisitor.cs
  39. +96 −0 src/FluentNHibernate/IRepository.cs
  40. +68 −0 src/FluentNHibernate/InMemoryRepository.cs
  41. +93 −0 src/FluentNHibernate/Mapping/ClassMap.cs
  42. +107 −0 src/FluentNHibernate/Mapping/ClassMapBase.cs
  43. +41 −0 src/FluentNHibernate/Mapping/ClassToTableMapping.cs
  44. +36 −0 src/FluentNHibernate/Mapping/ComponentPart.cs
  45. +17 −0 src/FluentNHibernate/Mapping/DefaultConvention.cs
  46. +72 −0 src/FluentNHibernate/Mapping/DiscriminatorPart.cs
  47. +21 −0 src/FluentNHibernate/Mapping/EnumerationTypeConvention.cs
  48. +13 −0 src/FluentNHibernate/Mapping/GenericEnumMapper.cs
  49. +15 −0 src/FluentNHibernate/Mapping/IMapping.cs
  50. +19 −0 src/FluentNHibernate/Mapping/IProperty.cs
  51. +11 −0 src/FluentNHibernate/Mapping/ITypeConvention.cs
  52. +35 −0 src/FluentNHibernate/Mapping/IdentityPart.cs
  53. +17 −0 src/FluentNHibernate/Mapping/IgnoreNullableTypeConvention.cs
  54. +53 −0 src/FluentNHibernate/Mapping/ManyToManyPart.cs
  55. +43 −0 src/FluentNHibernate/Mapping/ManyToOnePart.cs
  56. +60 −0 src/FluentNHibernate/Mapping/OneToManyPart.cs
  57. +115 −0 src/FluentNHibernate/Mapping/PropertyMap.cs
  58. +34 −0 src/FluentNHibernate/Mapping/SubClassPart.cs
  59. +4 −0 src/FluentNHibernate/Mapping/Template.xml
  60. +12 −0 src/FluentNHibernate/Mapping/TypeMapping.cs
  61. +64 −0 src/FluentNHibernate/Mapping/XmlExtensions.cs
  62. +48 −0 src/FluentNHibernate/MappingVisitor.cs
  63. +139 −0 src/FluentNHibernate/Metadata/DependencyChain.cs
  64. +132 −0 src/FluentNHibernate/PersistenceModel.cs
  65. +178 −0 src/FluentNHibernate/PersistenceSpecification.cs
  66. +192 −0 src/FluentNHibernate/Query/EntityQueryDefinition.cs
  67. +178 −0 src/FluentNHibernate/Query/FilterType.cs
  68. +69 −0 src/FluentNHibernate/SessionSource.cs
  69. BIN  tools/NHibernate/Castle.Core.dll
  70. +3,049 −0 tools/NHibernate/Castle.Core.xml
  71. +13 −0 tools/NHibernate/Castle.DynamicProxy.license.txt
  72. BIN  tools/NHibernate/Castle.DynamicProxy2.dll
  73. +635 −0 tools/NHibernate/Castle.DynamicProxy2.xml
  74. BIN  tools/NHibernate/Iesi.Collections.Test.dll
  75. +211 −0 tools/NHibernate/Iesi.Collections.Test.dll-results.xml
  76. BIN  tools/NHibernate/Iesi.Collections.Test.pdb
  77. BIN  tools/NHibernate/Iesi.Collections.dll
  78. +9 −0 tools/NHibernate/Iesi.Collections.license.txt
  79. BIN  tools/NHibernate/Iesi.Collections.pdb
  80. +1,887 −0 tools/NHibernate/Iesi.Collections.xml
  81. BIN  tools/NHibernate/Lucene.Net.dll
  82. +6,740 −0 tools/NHibernate/Lucene.Net.xml
  83. BIN  tools/NHibernate/NHibernate.DomainModel.dll
  84. BIN  tools/NHibernate/NHibernate.DomainModel.pdb
  85. +1,271 −0 tools/NHibernate/NHibernate.DomainModel.xml
  86. BIN  tools/NHibernate/NHibernate.Examples.dll
  87. +53 −0 tools/NHibernate/NHibernate.Examples.dll.config
  88. BIN  tools/NHibernate/NHibernate.Examples.pdb
  89. BIN  tools/NHibernate/NHibernate.Linq.dll
  90. BIN  tools/NHibernate/NHibernate.Linq.pdb
  91. BIN  tools/NHibernate/NHibernate.Test.Performance.dll
  92. +85 −0 tools/NHibernate/NHibernate.Test.Performance.dll.config
  93. BIN  tools/NHibernate/NHibernate.Test.Performance.pdb
  94. BIN  tools/NHibernate/NHibernate.Test.dll
  95. +3,322 −0 tools/NHibernate/NHibernate.Test.dll-results.xml
  96. +136 −0 tools/NHibernate/NHibernate.Test.dll.config
  97. BIN  tools/NHibernate/NHibernate.Test.pdb
  98. BIN  tools/NHibernate/NHibernate.Tool.HbmXsd.exe
  99. BIN  tools/NHibernate/NHibernate.Tool.HbmXsd.pdb
  100. BIN  tools/NHibernate/NHibernate.dll
  101. +460 −0 tools/NHibernate/NHibernate.license.txt
  102. BIN  tools/NHibernate/NHibernate.pdb
  103. +36,484 −0 tools/NHibernate/NHibernate.xml
  104. BIN  tools/NHibernate/Rhino.Mocks.dll
  105. +7,677 −0 tools/NHibernate/Rhino.Mocks.xml
  106. +11 −0 tools/NHibernate/TestEnbeddedConfig.cfg.xml
  107. BIN  tools/NHibernate/log4net.dll
  108. +201 −0 tools/NHibernate/log4net.license.txt
  109. +28,655 −0 tools/NHibernate/log4net.xml
  110. BIN  tools/NHibernate/nmock.dll
  111. +34 −0 tools/NHibernate/nmock.license.txt
  112. BIN  tools/NHibernate/nunit.core.dll
  113. BIN  tools/NHibernate/nunit.framework.dll
  114. +14 −0 tools/NHibernate/nunit.framework.license.txt
  115. BIN  tools/ShadeTree/ShadeTree.Core.dll
  116. BIN  tools/StructureMap/AxInterop.SHDocVw.dll
  117. BIN  tools/StructureMap/Interop.SHDocVw.dll
  118. BIN  tools/StructureMap/Microsoft.mshtml.dll
  119. BIN  tools/StructureMap/Rhino.Mocks.dll
  120. BIN  tools/StructureMap/StructureMap.AutoMocking.dll
  121. BIN  tools/StructureMap/StructureMap.AutoMocking.pdb
  122. BIN  tools/StructureMap/StructureMap.Client.dll
  123. BIN  tools/StructureMap/StructureMap.DataAccess.dll
  124. BIN  tools/StructureMap/StructureMap.DeploymentTasks.dll
  125. BIN  tools/StructureMap/StructureMap.dll
  126. BIN  tools/StructureMap/StructureMap.pdb
  127. BIN  tools/StructureMap/StructureMapDoctor.exe
  128. BIN  tools/StructureMap/StructureMapExplorer.exe
  129. BIN  tools/StructureMap/log4net.dll
  130. BIN  tools/StructureMap/nmock.dll
  131. BIN  tools/StructureMap/nunit.framework.dll
  132. BIN  tools/fit/FitLibrary.dll
  133. BIN  tools/fit/FitServer.exe
  134. BIN  tools/fit/TestRunner.exe
  135. BIN  tools/fit/fit.dll
  136. BIN  tools/fit/fitnesse.jar
  137. BIN  tools/rhino/Rhino.Mocks.dll
  138. +7,122 −0 tools/rhino/Rhino.Mocks.xml
  139. BIN  tools/rhino/Rhino.jpg
View
BIN  docs/logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
21 src/CommonAssemblyInfo.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1433
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+[assembly: AssemblyVersionAttribute("0.1.0.0")]
+[assembly: AssemblyCopyrightAttribute("Released by Jeremy D. Miller under the Apache 2.0 License")]
+[assembly: AssemblyProductAttribute("FluentNHibernate")]
+[assembly: AssemblyCompanyAttribute("FluentNHibernate")]
+[assembly: AssemblyConfigurationAttribute("debug")]
+[assembly: AssemblyInformationalVersionAttribute("0.1.0.0")]
+
View
14 src/FluentNHibernate.Testing/Debugging.cs
@@ -0,0 +1,14 @@
+using NUnit.Framework;
+
+namespace ShadeTree.Testing
+{
+ [TestFixture]
+ public class Debugging
+ {
+ [Test]
+ public void Break()
+ {
+ //Assert.Fail("Make it break");
+ }
+ }
+}
View
213 src/FluentNHibernate.Testing/DeclarativeTesting.htm
@@ -0,0 +1,213 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+ <head>
+ <title></title>
+ </head>
+ <body>
+ <p>Yesterday,
+ <a href="http://codebetter.com/blogs/david_laribee/archive/2008/06/17/test-your-nhibernate-mappings.aspx">David Laribee related some problems</a> he experienced with refactorings in his
+ domain model leading to some breaking problems with NHibernate mappings.&nbsp;
+ Specifically, the issues are:</p>
+ <ol>
+ <li>Changing the property names of a domain model can break the NHibernate mapping</li>
+ <li>Changing the database fields can break the NHibernate mappings</li>
+ </ol>
+ <p>
+ David went on to bemoan the absence of a quick way to validate NHibernate
+ mappings.&nbsp; Ayende popped in with the suggestion that the presence of
+ integrated tests around the NHibernate usage would spot mapping problems.&nbsp;
+ Other folks mentioned that there&#39;s a new ReSharper plugin to validate and
+ refactor NHibernate mappings.&nbsp; I&#39;ll circle back to the refactoring plugin
+ in a while.&nbsp; First I want to talk about quick ways to validate NHibernate
+ mappings.&nbsp; Ayende is right of course about the integrated tests against the
+ individual queries, but I&#39;m going to suggest that that isn&#39;t the most efficient
+ answer.&nbsp; The bigger integration tests will tell you that something is
+ wrong, but from experience they&#39;ll be harder to diagnose because there is so
+ much more going on than simple property checking, and they provide a slow
+ feedback cycle because of how much stuff is going on.&nbsp; What would be nice
+ is a way to walk right up to a mapping and specify which properties on a class
+ are supposed to be persisted and how.</p>
+ <p>
+ I thought I would come out of my blogging retirement and show an example of the
+ <a href="http://www.lostechies.com/blogs/chad_myers/archive/2008/06/02/a-new-start.aspx">Chad and Jeremy</a>
+ approach to testing NHibernate mappings:</p>
+ <pre name="code" class="c-sharp">
+
+ [SetUp]
+ public void SetUp()
+ {
+ // Ensure that the StructureMap configuration is bootstrapped
+ // In our case, this includes everything we need setup to
+ // execute NHibernate (mappings + ISessionFactory configuration)
+ // This will be pretty application specific here
+ Bootstrapper.RestartStructureMap();
+ }
+
+ [Test]
+ public void SaveAndLoadCustomerContact()
+ {
+ new PersistenceSpecification&lt;CustomerContact&gt;()
+ .CheckProperty(x =&gt; x.Name, "Frank")
+ .CheckProperty(x =&gt; x.Email, "Email")
+ .CheckProperty(x =&gt; x.Extension, 123)
+ .CheckProperty(x =&gt; x.FaxNumber, "111-111-1111")
+ .CheckProperty(x =&gt; x.TelephoneNumber, "222-222-2222")
+ .CheckProperty(x =&gt; x.Title, "Mr.")
+ .VerifyTheMappings();
+ }
+ </pre>
+ <p>
+ All this test does is ensure that the 6 properties of the CustomerContact class
+ (Name, Email, Extension, FaxNumber, TelephoneNumber, Title) are mapped in
+ NHibernate.&nbsp; We have some other methods for checking to many and many to
+ one type relationships.&nbsp; </p>
+ <p>
+ Behind the scenes the PersistenceSpecification&lt;T&gt; class:</p>
+ <ol>
+ <li>&nbsp;Creates a new instance of T</li>
+ <li>Uses the lambda expressions and suggested values in the calls to CheckProperty
+ to load values into the new instance of T</li>
+ <li>Grabs our IRepository out of StructureMap (of course), and saves the object</li>
+ <li>Grabs a second IRepository out of StructureMap</li>
+ <li>Fetches a second copy of the same T out of the second IRepository</li>
+ <li>Verifies that all of the specified properties in the specification were saved
+ and loaded.&nbsp; If any single property does not match between the first T and
+ the second T, the test will fail.</li>
+ </ol>
+ <p>Here's the implementation of the PersistenceSpecification.VerifyTheMappings() method:</p>
+ <pre name="code" class="c-sharp">
+ public void VerifyTheMappings()
+ {
+ // Create the initial copy
+ var first = new T();
+
+ // Set the "suggested" properties, including references
+ // to other entities and possibly collections
+ _allProperties.ForEach(p =&gt; p.SetValue(first));
+
+ // Save the first copy
+ _repository.Save(first);
+
+ // Get a completely different IRepository
+ var secondRepository = createRepository();
+
+ // "Find" the same entity from the second IRepository
+ var second = secondRepository.Find&lt;T&gt;(first.Id);
+
+ // Validate that each specified property and value
+ // made the round trip
+ // It's a bit naive right now because it fails on the first failure
+ _allProperties.ForEach(p =&gt; p.CheckValue(second));
+ }
+ </pre>
+
+ <p>The advantage of this testing is that it gives a (relatively) fast feedback cycle
+ focused specifically on the mappings.&nbsp; Tools that check the hbm.xml
+ mappings can only verify that what&#39;s there is correctly formed.&nbsp; The
+ mapping tests above will catch missing mappings and desired behavior.&nbsp; At a
+ bare minimum, you really should have at least one smoke test in your CI build
+ that simply tries to create an NHibernate ISession object from your
+ configuration.&nbsp; Let that test run and possibly fail before any integrated
+ tests run.</p>
+ <p>Now, the ReSharper plugin for NHibernate sounds pretty cool.&nbsp; I definitely
+ want little or no friction in renaming or adding properties in my Domain Model
+ classes (why I absolutely despise codegen your business object solutions).&nbsp;
+ We beat the refactoring problem by eliminating HBM.XML.&nbsp; As part of my New
+ Year&#39;s resolution to eliminate my exposure to angle bracket hell, we&#39;ve created
+ the beginning of a Fluent Interface API to express NHibernate mappings.&nbsp;
+ Using copious amounts of Generics (I guess .Net code just &quot;wants&quot; to have lots
+ of angle brackets) and lambda expressions, we&#39;re able to express NHibernate
+ mappings in a completely compiler-checked, ReSharper-able way.&nbsp; Since we
+ switched to the FI, we&#39;ve experienced far less trouble with mapping problems.&nbsp;
+ Here&#39;s a couple of examples:</p>
+
+ <pre name="code" class="c-sharp">
+ // Simple class with properties and a single "to-many" relationship
+ public class CustomerContactMap : ClassMap&lt;CustomerContact&gt;
+ {
+ public CustomerContactMap()
+ {
+ Map(x =&gt; x.Name);
+ Map(x =&gt; x.Email);
+ Map(x =&gt; x.Extension);
+ Map(x =&gt; x.FaxNumber);
+ Map(x =&gt; x.TelephoneNumber);
+ Map(x =&gt; x.Title);
+ References(x =&gt; x.Customer);
+ }
+ }
+
+ // Class with a "Component"
+ public class CustomerDeliveryAddressMap : ClassMap&lt;CustomerDeliveryAddress&gt;
+ {
+ public CustomerDeliveryAddressMap()
+ {
+ Map(x =&gt; x.Name);
+ References(x =&gt; x.Customer);
+ Component&lt;Address&gt;(x =&gt; x.Address, m =&gt;
+ {
+ m.Map(x =&gt; x.AddressLine1);
+ m.Map(x =&gt; x.AddressLine2);
+ m.Map(x =&gt; x.AddressLine3);
+ m.Map(x =&gt; x.CityName);
+ m.Map(x =&gt; x.CountryName);
+ m.References(x =&gt; x.State);
+ m.References(x =&gt; x.PostalCode);
+ });
+ }
+ }
+
+ // Class with some "has many" relationships
+ public class CustomerMap : ClassMap&lt;Customer&gt;
+ {
+ public CustomerMap()
+ {
+ HasMany&lt;CustomerContact&gt;(x =&gt; x.Contacts).CascadeAll();
+ HasMany&lt;CustomerJob&gt;(x =&gt; x.Jobs).CascadeAll();
+ HasMany&lt;CustomerDeliveryAddress&gt;(x =&gt; x.DeliveryAddresses).CascadeAll();
+
+ Map(x =&gt; x.Name);
+ Map(x =&gt; x.LookupName);
+ Map(x =&gt; x.IsGeneric);
+ Map(x =&gt; x.RequiresPurchaseOrder);
+ Map(x =&gt; x.Retired);
+ }
+ }
+
+
+ </pre>
+
+ <p>With this approach, and backed up with the little PersistenceSpecification tests,
+ we can happily change class names and property names with relative confidence.&nbsp;
+ Besides, the simple usage of Intellisense plus compiler safe code cuts down on
+ the number of mapping errors.&nbsp; We&#39;re more or less greenfield at the moment, so we can get away with generating
+ the database from our NHibernate mappings on demand, but you can specify
+ specific table and column names in the language above for brownfield scenarios.&nbsp;
+ I&#39;d very confidently say that we&#39;re faster with this approach than we would be
+ with HBM.XML.</p>
+ <p>If you're interested, the complete code for everything I talked about is in the ShadeTree.DomainModel project in the StoryTeller codebase (and effectively released under the Apache 2.0 license). The code is at
+ <a href="http://storyteller.tigris.org/svn/storyteller/trunk">http://storyteller.tigris.org/svn/storyteller/trunk/</a>. Use the src\ShadeTree.sln for this stuff. I don't know that we'll ever get around to a fully supported release of this stuff, but I wanted to throw out the idea anyway. At this point I'm only extending this code when we need something new for our current project.&nbsp;
+ A lot of the advantages of this approach are tied to application specific
+ conventions and also by tieing the forward generation of the database structure
+ to validation rules.</p>
+ <p>&nbsp;</p>
+
+ <h4>As for IoC container testing... </h4>
+ <p>I'll overlook the fact that my friend David implicitly implied that an
+ IoC container not named StructureMap was the de facto standard.
+ <a href="http://weblogs.asp.net/bsimser/archive/2008/06/04/the-first-spec-you-should-write-when-using-castle.aspx">Bil Simser posted a little snippet of code to smoke test the configuration</a> of one of those other IoC containers.&nbsp; StructureMap has had quite a bit
+ of diagnostic support since version 0.85, but StructureMap 2.5 will add the
+ ability to do this:</p>
+ <pre name="code" class="c-sharp">
+ [SetUp]
+ public void SmokeTestStructureMapConfiguration()
+ {
+ ObjectFactory.AssertConfigurationIsValid();
+ }
+ </pre>
+ <p>This will attempt to build every possible configured instance in StructureMap, perform any designated
+ <a href="http://codebetter.com/blogs/jeremy.miller/archive/2006/04/06/142431.aspx">environment tests</a> (like trying to connect to a database), and generate a complete report of all errors encountered by StructureMap.&nbsp;
+ If you&#39;re aggressive about putting all services into your IoC container, this
+ test can help measure the correctness of an installation.</p>
+ </body>
+</html>
View
278 src/FluentNHibernate.Testing/DomainModel/ConnectedTester.cs
@@ -0,0 +1,278 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using NHibernate;
+using NUnit.Framework;
+using ShadeTree.DomainModel;
+using ShadeTree.DomainModel.Fixtures;
+using ShadeTree.DomainModel.Mapping;
+using NHibernate.Linq;
+using ShadeTree.DomainModel.Query;
+using StructureMap;
+
+namespace ShadeTree.Testing.DomainModel
+{
+ [TestFixture, Explicit]
+ public class ConnectedTester
+ {
+ private SessionSource _source;
+
+ [SetUp]
+ public void SetUp()
+ {
+ IDictionary<string, string> props = new Dictionary<string, string>();
+ props.Add("connection.provider", "NHibernate.Connection.DriverConnectionProvider");
+ props.Add("connection.driver_class", "NHibernate.Driver.SqlClientDriver");
+ props.Add("dialect", "NHibernate.Dialect.MsSql2000Dialect");
+ props.Add("hibernate.dialect", "NHibernate.Dialect.MsSql2000Dialect");
+ props.Add("use_outer_join", "true");
+ props.Add("connection.connection_string", "Data Source=.;Initial Catalog=ShadeTree;Integrated Security=True;Pooling=False");
+ //props.Add("show_sql", showSql);
+ props.Add("show_sql", true.ToString());
+
+ _source = new SessionSource(props, new TestModel());
+
+ _source.BuildSchema();
+
+ ObjectFactory.Inject<ISessionSource>(_source);
+ DomainObjectFinder.ClearAllFinders();
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ ObjectFactory.ResetDefaults();
+ }
+
+
+ [Test]
+ public void Spin_up_the_Linq_stuff()
+ {
+ ISession session = _source.CreateSession();
+
+ session.SaveOrUpdate(new Record{Name = "Jeremy", Age = 34});
+ session.SaveOrUpdate(new Record{Name = "Jessica", Age = 29});
+ session.SaveOrUpdate(new Record{Name = "Natalie", Age = 25});
+ session.SaveOrUpdate(new Record{Name = "Hank", Age = 29});
+ session.SaveOrUpdate(new Record{Name = "Darrell", Age = 34});
+ session.SaveOrUpdate(new Record{Name = "Bill", Age = 34});
+ session.SaveOrUpdate(new Record{Name = "Tim", Age = 35});
+ session.SaveOrUpdate(new Record{Name = "Greg", Age = 36});
+
+ //ISession session2 = _source.CreateSession();
+ //var query = from record in session2.Linq<Record>() where record.Age < 30 select record;
+ //foreach (Record record in query.ToList())
+ //{
+ // Debug.WriteLine(record.Name);
+ //}
+
+ //return;
+
+ Repository repository = new Repository(_source.CreateSession());
+ Record[] records = repository.Query<Record>(record => record.Age == 29);
+ //records.Length.ShouldEqual(2);
+
+ foreach (var record in records)
+ {
+ Debug.WriteLine(record.Name);
+ }
+ }
+
+ [Test]
+ public void QueryBy_test()
+ {
+ ISession session = _source.CreateSession();
+
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Jessica", Age = 29 });
+ session.SaveOrUpdate(new Record { Name = "Natalie", Age = 25 });
+ session.SaveOrUpdate(new Record { Name = "Hank", Age = 29 });
+ session.SaveOrUpdate(new Record { Name = "Darrell", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Bill", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Tim", Age = 35 });
+ session.SaveOrUpdate(new Record { Name = "Greg", Age = 36 });
+
+ Repository repository = new Repository(_source.CreateSession());
+ Record record = repository.FindBy<Record, string>(r => r.Name, "Hank");
+ record.Name.ShouldEqual("Hank");
+ }
+
+ [Test]
+ public void Query_by_filters()
+ {
+ ISession session = _source.CreateSession();
+
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 35 });
+ session.SaveOrUpdate(new Record { Name = "Jessica", Age = 29 });
+ session.SaveOrUpdate(new Record { Name = "Natalie", Age = 25 });
+ session.SaveOrUpdate(new Record { Name = "Hank", Age = 29 });
+ session.SaveOrUpdate(new Record { Name = "Darrell", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Bill", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Tim", Age = 35 });
+ session.SaveOrUpdate(new Record { Name = "Greg", Age = 36 });
+
+ Repository repository = new Repository(_source.CreateSession());
+ Record record = repository.FindBy<Record>(r => r.Age == 34 && r.Name == "Jeremy");
+ record.Name.ShouldEqual("Jeremy");
+ record.Age.ShouldEqual(34);
+ }
+
+ [Test]
+ public void Query_with_multiple_expressions()
+ {
+ ISession session = _source.CreateSession();
+
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 35 });
+
+ Repository repository = new Repository(_source.CreateSession());
+ Record[] records = repository.Query<Record>(r => r.Age >= 35 && r.Name == "Jeremy");
+
+ records.ShouldHaveCount(1);
+ records[0].Name.ShouldEqual("Jeremy");
+ records[0].Age.ShouldEqual(35);
+ }
+
+ [Test]
+ public void Try_out_EntityQuery()
+ {
+ var queryDef = new EntityQueryDefinitionBuilder<Record>()
+ .AllowFilterOn(r => r.Age)
+ .AllowFilterOn(r => r.Name)
+ .QueryDefinition;
+
+ ISession session = _source.CreateSession();
+
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 35 });
+
+ Repository repository = new Repository(_source.CreateSession());
+
+ var query = new EntityQueryBuilder<Record>(queryDef);
+ query.AddFilter(new BinaryFilterType { FilterExpressionType = ExpressionType.Equal }, queryDef.GetFilterPropertyForKey("Age"), "35");
+ query.AddFilter(new StringFilterType { StringMethod = s => s.EndsWith("") }, queryDef.GetFilterPropertyForKey("Name"), "emy");
+
+ Record[] records = repository.Query(query.FilterExpression);
+
+ records.ShouldHaveCount(1);
+ records[0].Name.ShouldEqual("Jeremy");
+ records[0].Age.ShouldEqual(35);
+ }
+
+ [Test]
+ public void Try_out_DomainObjectFinder()
+ {
+ ISession session = _source.CreateSession();
+
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 35 });
+ session.SaveOrUpdate(new Record { Name = "Jessica", Age = 29 });
+ session.SaveOrUpdate(new Record { Name = "Natalie", Age = 25 });
+ session.SaveOrUpdate(new Record { Name = "Hank", Age = 29 });
+ session.SaveOrUpdate(new Record { Name = "Darrell", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Bill", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Chad", Age = 35 });
+ session.SaveOrUpdate(new Record { Name = "Earl", Age = 36 });
+
+ Repository repository = new Repository(_source.CreateSession());
+ ObjectFactory.Inject<IRepository>(repository);
+
+
+
+
+ DomainObjectFinder.Type<Record>().IsFoundByProperty(r => r.Name);
+
+
+
+
+ Record record = DomainObjectFinder.Find<Record>("Chad");
+ record.Name.ShouldEqual("Chad");
+ }
+
+
+ [Test]
+ public void Try_out_DomainObjectFinder2()
+ {
+ ISession session = _source.CreateSession();
+
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Jeremy", Age = 35 });
+ session.SaveOrUpdate(new Record { Name = "Jessica", Age = 29 });
+ session.SaveOrUpdate(new Record { Name = "Natalie", Age = 25 });
+ session.SaveOrUpdate(new Record { Name = "Hank", Age = 29 });
+ session.SaveOrUpdate(new Record { Name = "Darrell", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Bill", Age = 34 });
+ session.SaveOrUpdate(new Record { Name = "Chad", Age = 35 });
+ session.SaveOrUpdate(new Record { Name = "Earl", Age = 36 });
+
+ Repository repository = new Repository(_source.CreateSession());
+ ObjectFactory.Inject<IRepository>(repository);
+
+
+
+
+ DomainObjectFinder.Type<Record>().IsFoundBy(name =>
+ {
+ return new Record{Name = name};
+ });
+
+
+ Record record = DomainObjectFinder.Find<Record>("Chad");
+ record.Name.ShouldEqual("Chad");
+ }
+
+ [Test]
+ public void Save_and_find()
+ {
+ Repository repository1 = new Repository(_source.CreateSession());
+ var record1 = new Record { Name = "Jeremy", Age = 34 };
+ repository1.Save(record1);
+
+ Repository repository2 = new Repository(_source.CreateSession());
+ Record record2 = repository2.Find<Record>(record1.Id);
+
+ record1.ShouldNotBeTheSameAs(record2);
+ record2.Name.ShouldEqual("Jeremy");
+ }
+
+ [Test]
+ public void MappingTest1()
+ {
+ new PersistenceSpecification<Record>()
+ .CheckProperty(r => r.Age, 22)
+ .CheckProperty(r => r.Name, "somebody")
+ .CheckProperty(r => r.Location, "somebody")
+ .VerifyTheMappings();
+
+ }
+ }
+
+ public class TestModel : PersistenceModel
+ {
+ public TestModel()
+ {
+ addMappingsFromThisAssembly();
+ }
+ }
+
+ public class RecordMap : ClassMap<Record>
+ {
+ public RecordMap()
+ {
+ UseIdentityForKey(x => x.Id, "id");
+ Map(x => x.Name);
+ Map(x => x.Age);
+ }
+ }
+
+ public class Record : Entity
+ {
+ public string Name { get; set; }
+ public int Age { get; set; }
+ public string Location { get; set; }
+ }
+}
View
92 src/FluentNHibernate.Testing/DomainModel/EntityEquality.cs
@@ -0,0 +1,92 @@
+using NUnit.Framework;
+using ShadeTree.DomainModel;
+
+namespace ShadeTree.Testing.DomainModel
+{
+ [TestFixture]
+ public class EntityEquality
+ {
+ [Test]
+ public void Two_entities_with_the_same_Id_should_equal_each_other()
+ {
+ var first = new Entity{Id = 99};
+ var second = new Entity { Id = 99 };
+
+ first.Equals(second).ShouldBeTrue();
+ second.Equals(first).ShouldBeTrue();
+
+
+ Equals(first, second).ShouldBeTrue();
+ Equals(second, first).ShouldBeTrue();
+
+ first.GetHashCode().ShouldEqual(second.GetHashCode());
+
+ (first == second).ShouldBeTrue();
+ (second == first).ShouldBeTrue();
+
+ (first != second).ShouldBeFalse();
+ (second != first).ShouldBeFalse();
+ }
+
+ [Test]
+ public void Two_entities_with_different_Ids_should_not_equal_each_other()
+ {
+ var first = new Entity { Id = 66 };
+ var second = new Entity { Id = 77 };
+
+ first.Equals(second).ShouldBeFalse();
+ second.Equals(first).ShouldBeFalse();
+
+
+ Equals(first, second).ShouldBeFalse();
+ Equals(second, first).ShouldBeFalse();
+
+ first.GetHashCode().ShouldNotEqual(second.GetHashCode());
+
+ (first == second).ShouldBeFalse();
+ (second == first).ShouldBeFalse();
+
+ (first != second).ShouldBeTrue();
+ (second != first).ShouldBeTrue();
+ }
+
+ [Test]
+ public void Subclassed_entities_should_equal_each_other_with_same_Id()
+ {
+ var first = new TestSubEntity {Id = 99};
+ var second = new TestSubEntity { Id = 99 };
+
+ first.Equals(second).ShouldBeTrue();
+ }
+
+ [Test]
+ public void Subclassed_entities_should_not_equal_entities_of_a_different_type_even_if_the_Id_is_the_same()
+ {
+ var first = new TestSubEntity { Id = 99 };
+ var second = new AnotherSubEntity { Id = 99 };
+
+ first.Equals(second).ShouldBeFalse();
+ }
+
+ [Test]
+ public void Deep_subclassed_entities_should_not_equal_their_parent_classed_entities_even_if_the_Id_is_the_same()
+ {
+ var first = new TestSubEntity { Id = 99 };
+ var second = new DeepSubEntity { Id = 99 };
+
+ first.Equals(second).ShouldBeFalse();
+ }
+
+ public class TestSubEntity : Entity
+ {
+ }
+
+ public class AnotherSubEntity : Entity
+ {
+ }
+
+ public class DeepSubEntity : TestSubEntity
+ {
+ }
+ }
+}
View
24 src/FluentNHibernate.Testing/DomainModel/Generation/CodeFileSmokeTester.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using ShadeTree.DomainModel.Generation;
+
+namespace ShadeTree.Testing.DomainModel.Generation
+{
+ [TestFixture]
+ public class CodeFileSmokeTester
+ {
+ [Test]
+ public void SmokeTest_Code_File()
+ {
+ CodeFile file = new CodeFile("Fixtures.cs", "DomainFixtureGeneration");
+ file.AddDomainType<Case>();
+ file.AddDomainType<Contact>();
+
+ file.WriteToConsole();
+ file.WriteToFile();
+ }
+ }
+}
View
85 src/FluentNHibernate.Testing/DomainModel/InMemoryRepositoryTester.cs
@@ -0,0 +1,85 @@
+using System.Diagnostics;
+using NUnit.Framework;
+using ShadeTree.DomainModel;
+
+namespace ShadeTree.Testing.DomainModel
+{
+ [TestFixture]
+ public class InMemoryRepositoryTester
+ {
+ [Test]
+ public void Store_and_find_two_different_types_of_objects()
+ {
+ InMemoryRepository repository = new InMemoryRepository();
+ repository.Save(new Case {Id = 2});
+ repository.Save(new Case {Id = 3});
+ repository.Save(new Contact {Id = 2});
+ repository.Save(new Contact {Id = 3});
+
+ repository.Find<Case>(2).Id.ShouldEqual(2);
+ repository.Find<Contact>(3).ShouldBeOfType(typeof(Contact));
+ repository.Find<Case>(3).ShouldBeOfType(typeof(Case));
+ }
+
+ [Test]
+ public void Query_by_expression()
+ {
+ InMemoryRepository repository = new InMemoryRepository();
+ repository.Save(new Case{Name = "Jeremy", Number = 10});
+ repository.Save(new Case{Name = "Darth Vader", Number = 5});
+ repository.Save(new Case{Name = "Darth Maul", Number = 6});
+ repository.Save(new Case{Name = "Luke", Number = 12});
+ repository.Save(new Case{Name = "Han Solo", Number = 6});
+ repository.Save(new Case{Name = "Eric", Number = 5});
+ repository.Save(new Case{Name = "Corwin", Number = 4});
+
+ repository.Query<Case>(c => c.Name.StartsWith("Darth")).Length.ShouldEqual(2);
+ repository.Query<Case>(c => c.Number == 6).Length.ShouldEqual(2);
+ Case[] cases = repository.Query<Case>(c => c.Number > 5);
+ cases.Length.ShouldEqual(4);
+ }
+
+ [Test]
+ public void Find_by_property()
+ {
+ InMemoryRepository repository = new InMemoryRepository();
+ repository.Save(new Case { Name = "Jeremy", Number = 10 });
+ repository.Save(new Case { Name = "Darth Vader", Number = 5 });
+ repository.Save(new Case { Name = "Darth Maul", Number = 6 });
+ repository.Save(new Case { Name = "Luke", Number = 12 });
+ repository.Save(new Case { Name = "Han Solo", Number = 6 });
+ repository.Save(new Case { Name = "Eric", Number = 5 });
+ repository.Save(new Case { Name = "Corwin", Number = 4 });
+
+ repository.FindBy<Case, string>(c => c.Name, "Jeremy").Name.ShouldEqual("Jeremy");
+ }
+
+ [Test]
+ public void Find_by_query()
+ {
+ InMemoryRepository repository = new InMemoryRepository();
+ repository.Save(new Case { Name = "Jeremy", Number = 10 });
+ repository.Save(new Case { Name = "Darth Vader", Number = 5 });
+ repository.Save(new Case { Name = "Darth Maul", Number = 6 });
+ repository.Save(new Case { Name = "Luke", Number = 12 });
+ repository.Save(new Case { Name = "Han Solo", Number = 6 });
+ repository.Save(new Case { Name = "Eric", Number = 5 });
+ repository.Save(new Case { Name = "Corwin", Number = 4 });
+
+ repository.FindBy<Case>(c => c.Name == "Corwin").Name.ShouldEqual("Corwin");
+ repository.FindBy<Case>(c => c.Number == 10).Name.ShouldEqual("Jeremy");
+ repository.FindBy<Case>(c => c.Number == 6 && c.Name == "Han Solo").Name.ShouldEqual("Han Solo");
+ }
+
+ }
+
+ public class Case : Entity
+ {
+ public long Number { get; set; }
+ public string Name { get; set; }
+ }
+
+ public class Contact : Entity
+ {
+ }
+}
View
390 src/FluentNHibernate.Testing/DomainModel/Mapping/ClassMapXmlCreationTester.cs
@@ -0,0 +1,390 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Xml;
+using NUnit.Framework;
+using ShadeTree.DomainModel;
+using ShadeTree.DomainModel.Mapping;
+using ShadeTree.Validation;
+
+namespace ShadeTree.Testing.DomainModel.Mapping
+{
+ [TestFixture]
+ public class ClassMapXmlCreationTester
+ {
+ #region Setup/Teardown
+
+ [SetUp]
+ public void SetUp()
+ {
+ }
+
+ #endregion
+
+ private XmlDocument document;
+
+ private XmlElement elementForProperty(string propertyName)
+ {
+ string xpath = string.Format("class/property[@name='{0}']", propertyName);
+ return (XmlElement) document.DocumentElement.SelectSingleNode(xpath);
+ }
+
+ [Test, Ignore("Needs to be rewritten at some point")]
+ public void BasicManyToManyMapping()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.HasManyToMany<ChildObject>(x => x.Children);
+
+ document = map.CreateMapping(new MappingVisitor());
+ var element = (XmlElement) document.DocumentElement.SelectSingleNode("class/bag[@name='Children']");
+
+ element.AttributeShouldEqual("name", "Children");
+ element.AttributeShouldEqual("cascade", "none");
+
+ element["key"].AttributeShouldEqual("column", "MappedObject_Fk");
+ element["many-to-many"].AttributeShouldEqual("class", typeof (ChildObject).AssemblyQualifiedName);
+ element["many-to-many"].AttributeShouldEqual("table", typeof (ChildObject).Name);
+ element["many-to-many"].AttributeShouldEqual("column", "ChildObject_Fk");
+ }
+
+ [Test]
+ public void BasicOneToManyMapping()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.HasMany<ChildObject>(x => x.Children);
+
+ document = map.CreateMapping(new MappingVisitor());
+
+ var element =
+ (XmlElement) document.DocumentElement.SelectSingleNode("class/bag[@name='Children']");
+
+ element.AttributeShouldEqual("name", "Children");
+ element.AttributeShouldEqual("cascade", "none");
+
+ element["key"].AttributeShouldEqual("column", "MappedObject_id");
+ element["one-to-many"].AttributeShouldEqual("class", typeof (ChildObject).AssemblyQualifiedName);
+ }
+
+ [Test]
+ public void AdvancedOneToManyMapping()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.HasMany<ChildObject>(x => x.Children).LazyLoad().IsInverse();
+
+ document = map.CreateMapping(new MappingVisitor());
+
+ var element =
+ (XmlElement)document.DocumentElement.SelectSingleNode("class/bag[@name='Children']");
+
+ element.AttributeShouldEqual("lazy", "true");
+ element.AttributeShouldEqual("inverse", "true");
+ }
+
+ [Test]
+ public void BuildTheHeaderXmlWithAssemblyAndNamespace()
+ {
+ var map = new ClassMap<MappedObject>();
+ document = map.CreateMapping(new MappingVisitor());
+
+ document.DocumentElement.GetAttribute("assembly").ShouldEqual(typeof (MappedObject).Assembly.GetName().Name);
+ document.DocumentElement.GetAttribute("namespace").ShouldEqual(typeof (MappedObject).Namespace);
+ }
+
+ [Test]
+ public void CascadeAll_with_many_to_many()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.HasManyToMany<ChildObject>(x => x.Children).CascadeAll();
+
+ document = map.CreateMapping(new MappingVisitor());
+ var element = (XmlElement) document.DocumentElement.SelectSingleNode("class/bag[@name='Children']");
+
+ element.AttributeShouldEqual("cascade", "all");
+ }
+
+ [Test]
+ public void CascadeAll_with_one_to_many()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.HasMany<ChildObject>(x => x.Children).CascadeAll();
+
+ document = map.CreateMapping(new MappingVisitor());
+ var element =
+ (XmlElement) document.DocumentElement.SelectSingleNode("class/bag[@name='Children']");
+
+ element.AttributeShouldEqual("cascade", "all");
+ }
+
+ [Test]
+ public void Create_a_component_mapping()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.Component<ComponentOfMappedObject>(x => x.Component, c =>
+ {
+ c.Map(x => x.Name);
+ c.Map(x => x.Age);
+ });
+
+ document = map.CreateMapping(new MappingVisitor());
+
+ var componentElement =
+ (XmlElement) document.DocumentElement.SelectSingleNode("class/component");
+
+ componentElement.AttributeShouldEqual("name", "Component");
+ componentElement.AttributeShouldEqual("insert", "true");
+ componentElement.AttributeShouldEqual("update", "true");
+
+ componentElement.ShouldHaveChild("property[@name='Name']");
+ componentElement.ShouldHaveChild("property[@name='Age']");
+ }
+
+
+ [Test]
+ public void
+ Create_a_component_mapping_for_a_component_that_is_not_required_and_the_fields_for_the_component_should_not_be_non_null
+ ()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.Component<SecondMappedObject>(x => x.Parent, c => { c.Map(x => x.Name); });
+
+ document = map.CreateMapping(new MappingVisitor());
+
+ var element =
+ (XmlElement) document.DocumentElement.SelectSingleNode("class/component/property[@name='Name']");
+
+ Debug.WriteLine(element.OuterXml);
+
+ element.HasAttribute("not-null").ShouldBeFalse();
+ }
+
+ [Test]
+ public void Create_a_component_mapping_for_a_required_child_and_set_the_required_fields_of_component_to_non_null
+ ()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.Component<ComponentOfMappedObject>(x => x.Component, c =>
+ {
+ c.Map(x => x.Name);
+ c.Map(x => x.Age);
+ });
+
+ document = map.CreateMapping(new MappingVisitor());
+
+ var componentElement =
+ (XmlElement) document.DocumentElement.SelectSingleNode("class/component");
+
+ var propertyElement = (XmlElement) componentElement.SelectSingleNode("property[@name = 'Age']");
+ propertyElement.AttributeShouldEqual("not-null", "true");
+ }
+
+ [Test]
+ public void CreateDiscriminator()
+ {
+ var map = new ClassMap<SecondMappedObject>();
+ map.DiscriminateSubClassesOnColumn<string>("Type");
+
+ document = map.CreateMapping(new MappingVisitor());
+ var element = (XmlElement) document.DocumentElement.SelectSingleNode("class/discriminator");
+ element.AttributeShouldEqual("column", "Type");
+ element.AttributeShouldEqual("type", "String");
+ }
+
+ [Test]
+ public void CreateTheSubClassMappings()
+ {
+ var map = new ClassMap<MappedObject>();
+
+ map.DiscriminateSubClassesOnColumn<string>("Type")
+ .SubClass<SecondMappedObject>().IsIdentifiedBy("red")
+ .MapSubClassColumns(m => { m.Map(x => x.Name); });
+
+ document = map.CreateMapping(new MappingVisitor());
+
+ Debug.WriteLine(document.OuterXml);
+
+ var element = (XmlElement) document.DocumentElement.SelectSingleNode("//subclass");
+ element.AttributeShouldEqual("name", "SecondMappedObject");
+ element.AttributeShouldEqual("discriminator-value", "red");
+
+ XmlElement propertyElement = element["property"];
+ propertyElement.AttributeShouldEqual("column", "Name");
+ }
+
+ [Test]
+ public void Creating_a_many_to_one_reference()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.References(x => x.Parent);
+
+ document = map.CreateMapping(new MappingVisitor());
+ var element = (XmlElement) document.DocumentElement.SelectSingleNode("class/many-to-one");
+
+ element.AttributeShouldEqual("name", "Parent");
+ element.AttributeShouldEqual("cascade", "all");
+ element.AttributeShouldEqual("column", "Parent_id");
+ }
+
+ [Test]
+ public void Creating_a_many_to_one_reference_sets_the_column_overrides()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.References(x => x.Parent);
+
+ document = map.CreateMapping(new MappingVisitor());
+
+ Debug.WriteLine(document.DocumentElement.OuterXml);
+
+ var element = (XmlElement)document.DocumentElement.SelectSingleNode("class/many-to-one");
+
+ element.AttributeShouldEqual("foreign-key", "FK_MappedObjectToParent");
+ }
+
+ [Test]
+ public void DetermineTheTableName()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.TableName.ShouldEqual("MappedObject");
+
+ map.TableName = "Different";
+ map.TableName.ShouldEqual("Different");
+ }
+
+ [Test]
+ public void DomainClassMapAutomaticallyCreatesTheId()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.UseIdentityForKey(x => x.Id, "id");
+ document = map.CreateMapping(new MappingVisitor());
+
+ XmlElement idElement = document.DocumentElement["class"]["id"];
+ idElement.ShouldNotBeNull();
+
+ idElement.GetAttribute("name").ShouldEqual("Id");
+ idElement.GetAttribute("column").ShouldEqual("id");
+ idElement.GetAttribute("type").ShouldEqual("Int64");
+ idElement.GetAttribute("unsaved-value").ShouldEqual("0");
+
+ XmlElement generatorElement = idElement["generator"];
+ generatorElement.ShouldNotBeNull();
+ generatorElement.GetAttribute("class").ShouldEqual("identity");
+ }
+
+ [Test]
+ public void Map_an_enumeration()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.Map(x => x.Color);
+
+ document = map.CreateMapping(new MappingVisitor());
+ XmlElement element = elementForProperty("Color");
+
+ Debug.WriteLine(element.OuterXml);
+
+ element.AttributeShouldEqual("type", typeof (GenericEnumMapper<ColorEnum>).AssemblyQualifiedName);
+ element["column"].AttributeShouldEqual("name", "Color");
+ element["column"].AttributeShouldEqual("sql-type", "string");
+ element["column"].AttributeShouldEqual("length", "50");
+ }
+
+ [Test]
+ public void MapASimplePropertyWithNoOverrides()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.Map(x => x.Name);
+
+ document = map.CreateMapping(new MappingVisitor());
+ XmlElement element = elementForProperty("Name");
+
+ element.AttributeShouldEqual("name", "Name");
+ element.AttributeShouldEqual("column", "Name");
+ element.AttributeShouldEqual("type", "String");
+ }
+
+ [Test]
+ public void SimpleProperty_picks_up_maximum_length_for_string_fields()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.Map(x => x.Name);
+ map.Map(x => x.NickName);
+
+ document = map.CreateMapping(new MappingVisitor());
+
+ Debug.WriteLine(document.DocumentElement.OuterXml);
+
+ elementForProperty("Name").AttributeShouldEqual("length", "100");
+ elementForProperty("NickName").AttributeShouldEqual("length", "10");
+ }
+
+ [Test]
+ public void SimpleProperty_picks_up_not_null_for_required()
+ {
+ var map = new ClassMap<MappedObject>();
+ map.Map(x => x.Name);
+ map.Map(x => x.NickName);
+
+ document = map.CreateMapping(new MappingVisitor());
+ elementForProperty("Name").AttributeShouldEqual("not-null", "true");
+ elementForProperty("NickName").DoesNotHaveAttribute("not-null");
+ }
+
+ [Test]
+ public void WriteTheClassNode()
+ {
+ var map = new ClassMap<MappedObject>();
+ document = map.CreateMapping(new MappingVisitor());
+
+ XmlElement classElement = document.DocumentElement["class"];
+ classElement.ShouldNotBeNull();
+
+ classElement.AttributeShouldEqual("name", typeof (MappedObject).Name);
+ classElement.AttributeShouldEqual("table", map.TableName);
+ }
+ }
+
+ public class SecondMappedObject
+ {
+ [Required]
+ public string Name { get; set; }
+ public long Id { get; set; }
+ }
+
+ public class ComponentOfMappedObject
+ {
+ public string Name { get; set; }
+
+ [Required]
+ public int Age { get; set; }
+ }
+
+ public enum ColorEnum
+ {
+ Blue,
+ Green,
+ Red
+ }
+
+ public class MappedObject
+ {
+ public ColorEnum Color { get; set; }
+
+ [Required]
+ public ComponentOfMappedObject Component { get; set; }
+
+ public SecondMappedObject Parent { get; set; }
+
+ [Required]
+ public string Name { get; set; }
+
+ [MaximumStringLength(10)]
+ public string NickName { get; set; }
+
+
+ public IList<ChildObject> Children { get; set; }
+
+ public long Id { get; set; }
+ }
+
+ public class ChildObject
+ {
+ public int Id { get; set; }
+ }
+}
View
94 src/FluentNHibernate.Testing/DomainModel/Mapping/ConventionsTester.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Reflection;
+using NUnit.Framework;
+using Rhino.Mocks;
+using ShadeTree.Core;
+using ShadeTree.Core.Validation;
+using ShadeTree.DomainModel;
+using ShadeTree.DomainModel.Mapping;
+
+namespace ShadeTree.Testing.DomainModel.Mapping
+{
+ [TestFixture]
+ public class ConventionsTester
+ {
+ [Test]
+ public void Set_the_convention_for_foreign_keys()
+ {
+ new Conventions().GetForeignKeyNameOfParent(typeof (Invoice)).ShouldEqual("Invoice_id");
+ }
+
+ [Test]
+ public void Get_the_convention_for_a_relationship()
+ {
+ new Conventions().GetForeignKeyName(typeof (Site).GetProperty("Primary")).ShouldEqual("Primary_id");
+ }
+
+ [Test]
+ public void add_property_convention_for_type_of_attribute()
+ {
+ MockRepository mocks = new MockRepository();
+ IProperty property = mocks.DynamicMock<IProperty>();
+
+
+ using (mocks.Record())
+ {
+ PropertyInfo propertyInfo = ReflectionHelper.GetProperty<Site>(s => s.Name);
+ Expect.Call(property.Property).Return(propertyInfo).Repeat.Any();
+ Expect.Call(property.PropertyType).Return(typeof(string)).Repeat.Any();
+
+ property.SetAttributeOnColumnElement("My", "true");
+ }
+
+ using (mocks.Playback())
+ {
+ var conventions = new Conventions();
+ conventions.ForAttribute<MyAttribute>((a, p) => p.SetAttributeOnColumnElement("My", "true"));
+ conventions.AlterMap(property);
+ }
+ }
+
+ [Test]
+ public void add_unique_property_for_Unique_attribute_by_default()
+ {
+ MockRepository mocks = new MockRepository();
+ IProperty property = mocks.DynamicMock<IProperty>();
+
+
+ using (mocks.Record())
+ {
+ PropertyInfo propertyInfo = ReflectionHelper.GetProperty<Site>(s => s.LastName);
+ Expect.Call(property.Property).Return(propertyInfo).Repeat.Any();
+ Expect.Call(property.PropertyType).Return(typeof(string)).Repeat.Any();
+
+ property.SetAttributeOnColumnElement("unique", "true");
+ }
+
+ using (mocks.Playback())
+ {
+ var conventions = new Conventions();
+ conventions.AlterMap(property);
+ }
+ }
+ }
+
+ public class Invoice{}
+
+ public class Site
+ {
+ [My]
+ public string Name { get; set; }
+
+ [Unique]
+ public string LastName { get; set; }
+
+ public Address Primary { get; set; }
+ public Address Secondary { get; set; }
+ }
+ public class Address{}
+
+ public class MyAttribute : Attribute
+ {
+
+ }
+}
View
33 src/FluentNHibernate.Testing/DomainModel/Mapping/PropertyMapTester.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Xml;
+using NUnit.Framework;
+using ShadeTree.Core;
+using ShadeTree.DomainModel;
+using ShadeTree.DomainModel.Mapping;
+
+namespace ShadeTree.Testing.DomainModel.Mapping
+{
+ [TestFixture]
+ public class PropertyMapTester
+ {
+ [Test]
+ public void SetAttributeOnColumnElement()
+ {
+ PropertyInfo property = ReflectionHelper.GetProperty<PropertyTarget>(x => x.Name);
+ var map = new PropertyMap(property, false, property.Name, typeof(PropertyTarget));
+ map.SetAttributeOnColumnElement("unique", "true");
+
+ var document = new XmlDocument();
+ XmlElement classElement = document.CreateElement("root");
+ map.Write(classElement, new MappingVisitor());
+
+ var columnElement = (XmlElement) classElement.SelectSingleNode("property/column");
+ columnElement.AttributeShouldEqual("unique", "true");
+ }
+ }
+
+ public class PropertyTarget
+ {
+ public string Name { get; set; }
+ }
+}
View
179 src/FluentNHibernate.Testing/DomainModel/Query/EntityQueryDefinitionTester.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using NUnit.Framework;
+using ShadeTree.DomainModel;
+using ShadeTree.DomainModel.Query;
+
+namespace ShadeTree.Testing.DomainModel.Query
+{
+ public class FooClass
+ {
+ public string foo { get; set; }
+ }
+
+ [TestFixture]
+ public class EntityQueryDefinitionTester
+ {
+ [Test]
+ public void AddQuickFilterFor_should_add_new_FilterableProperty_to_the_quick_filters_collection_as_well_as_the_general_filter_collection()
+ {
+ var query = new EntityQueryDefinition();
+ var filterProp = FilterableProperty.Build<FooClass, string>(x => x.foo);
+
+ query.AddQuickFilterProperty(filterProp);
+
+ query.QuickFilterProperties.ShouldHaveCount(1);
+ query.FilterableProperties.ShouldHaveCount(1);
+ }
+
+ [Test]
+ public void AllowFilterOn_should_add_new_FilterableProperty_to_the_query_filter_collection()
+ {
+ var query = new EntityQueryDefinition();
+ var filterProp = FilterableProperty.Build<FooClass, string>(x => x.foo);
+
+ query.AddFilterProperty(filterProp);
+
+ query.FilterableProperties.ShouldHaveCount(1);
+ }
+ }
+
+ [TestFixture]
+ public class EntityQueryDefinitionBuilderTester
+ {
+ [Test]
+ public void
+ AddQuickFilterFor_should_add_new_FilterableProperty_to_the_quick_filters_collection_as_well_as_the_general_filter_collection
+ ()
+ {
+ var query = new EntityQueryDefinitionBuilder<QueryDefTestEntity>();
+
+ query.AddQuickFilterFor(t => t.Name);
+
+ query.QueryDefinition.QuickFilterProperties.ShouldHaveCount(1);
+ query.QueryDefinition.FilterableProperties.ShouldHaveCount(1);
+ }
+
+ [Test]
+ public void AllowFilterOn_should_add_new_FilterableProperty_to_the_query_filter_collection()
+ {
+ var query = new EntityQueryDefinitionBuilder<QueryDefTestEntity>();
+
+ query.AllowFilterOn(t => t.Name);
+
+ query.QueryDefinition.FilterableProperties.ShouldHaveCount(1);
+ }
+ }
+
+ [TestFixture]
+ public class EntityQueryBuilderTester
+ {
+ #region Setup/Teardown
+
+ [SetUp]
+ public void SetUp()
+ {
+ _queryDef = new EntityQueryDefinition();
+ _query = new EntityQueryBuilder<QueryDefTestEntity>(_queryDef);
+
+ _nameProp = FilterableProperty.Build<QueryDefTestEntity, string>(t => t.Name);
+ _nameProp.PropertyType.ShouldEqual(typeof (string));
+
+ _ageProp = FilterableProperty.Build<QueryDefTestEntity, int>(t => t.Age);
+
+ FilterTypeRegistry.ResetAll();
+ }
+
+ #endregion
+
+ private EntityQueryBuilder<QueryDefTestEntity> _query;
+ private FilterableProperty _nameProp;
+ private FilterableProperty _ageProp;
+ private EntityQueryDefinition _queryDef;
+
+ [Test]
+ public void EntityQueryBuilder_AddFilter_should_add_a_new_filter_and_add_it_to_the_previous_filter_using_the_AndAlso_operator()
+ {
+ _query.AddFilter(new StringFilterType {StringMethod = s => s.StartsWith("")}, _nameProp, "Fo");
+ _query.AddFilter(new BinaryFilterType {FilterExpressionType = ExpressionType.Equal}, _ageProp, "35");
+
+ _query.FilterExpression.ToString().Contains("&&").ShouldBeTrue();
+ }
+
+ [Test]
+ public void EntityQueryBuilder_AddFilter_should_change_the_type_if_the_value_type_is_not_a_string()
+ {
+ _query.AddFilter(new BinaryFilterType {FilterExpressionType = ExpressionType.Equal}, _ageProp, "35");
+
+ _query.FilterExpression.ToString().Contains("ChangeType").ShouldBeTrue();
+ }
+
+ [Test]
+ public void EntityQueryBuilder_AddFilter_should_not_change_the_type_if_the_value_type_is_already_a_string()
+ {
+ _query.AddFilter(new StringFilterType {StringMethod = s => s.StartsWith("")}, _nameProp, "Fo");
+
+ _query.FilterExpression.ToString().Contains("ChangeType").ShouldBeFalse();
+ }
+
+ [Test]
+ public void EntityQueryBuilder_AddFilter_SmokeTest()
+ {
+ _query.AddFilter(new StringFilterType {StringMethod = s => s.StartsWith("")}, _nameProp, "Fo");
+ _query.AddFilter(new BinaryFilterType {FilterExpressionType = ExpressionType.Equal}, _ageProp, "35");
+
+ var itemList = new List<QueryDefTestEntity>
+ {
+ new QueryDefTestEntity {Name = "Bar", Age = 99},
+ new QueryDefTestEntity {Name = "Foo", Age = 35},
+ new QueryDefTestEntity {Name = "Baz", Age = 1}
+ };
+
+ QueryDefTestEntity[] values = itemList.AsQueryable().Where(_query.FilterExpression).ToArray();
+
+ values.Length.ShouldEqual(1);
+ values[0].Name.ShouldEqual("Foo");
+ values[0].Age.ShouldEqual(35);
+ }
+
+ [Test]
+ public void EntityQueryBuilder_PrepareQuery_should_loop_through_each_criterion_and_set_up_a_filter()
+ {
+ var repo = new InMemoryRepository();
+ repo.Save(new QueryDefTestEntity {Name = "Bar", Age = 99});
+ repo.Save(new QueryDefTestEntity {Name = "Foo", Age = 35});
+ repo.Save(new QueryDefTestEntity {Name = "Baz", Age = 1});
+
+ FilterTypeRegistry.ClearAll();
+
+ FilterTypeRegistry.RegisterFilter(
+ new StringFilterType
+ {
+ Key = "StringFoo",
+ StringMethod = s => s.StartsWith("")
+ })
+ .ForType<string>();
+
+ _queryDef.AddFilterProperty(FilterableProperty.Build<QueryDefTestEntity, string>(t => t.Name));
+
+
+ var crit = new Criteria
+ {property = "Name", op = "StringFoo", value = "Fo"};
+
+ QueryDefTestEntity[] values =
+ _query.PrepareQuery(new[] {crit}, repo).Cast<QueryDefTestEntity>().ToArray();
+
+ values.Length.ShouldEqual(1);
+ values[0].Name.ShouldEqual("Foo");
+ values[0].Age.ShouldEqual(35);
+ }
+ }
+
+ public class QueryDefTestEntity
+ {
+ public string Name { get; set; }
+ public int Age { get; set; }
+ }
+}
View
29 src/FluentNHibernate.Testing/DomainModel/Query/FilterTypeRegistryTester.cs
@@ -0,0 +1,29 @@
+using NUnit.Framework;
+using ShadeTree.DomainModel.Query;
+
+namespace ShadeTree.Testing.DomainModel.Query
+{
+ [TestFixture]
+ public class FilterTypeRegistryTester
+ {
+ [SetUp]
+ public void SetUp()
+ {
+ FilterTypeRegistry.ResetAll();
+ }
+
+ [Test]
+ public void should_return_expected_filter_types_for_string_type()
+ {
+ var filters = FilterTypeRegistry.GetFiltersFor<string>();
+ filters.ShouldContain(x => x.Key == "STARTSWITH");
+ }
+
+ [Test]
+ public void should_return_expected_filter_types_for_int32_type()
+ {
+ var filters = FilterTypeRegistry.GetFiltersFor<int>();
+ filters.ShouldContain(x => x.Key == "EQUAL");
+ }
+ }
+}
View
61 src/FluentNHibernate.Testing/DomainModel/Query/FilterTypeTester.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Linq.Expressions;
+using NUnit.Framework;
+using ShadeTree.DomainModel.Query;
+
+namespace ShadeTree.Testing.DomainModel.Query
+{
+ [TestFixture]
+ public class StringFilterTypeTester : FilterTypeSpec<StringFilterType, FilterTestEntity>
+ {
+ [Test]
+ public void StringFilterType_should_generate_an_expression_that_calls_the_designated_string_method_on_the_value()
+ {
+ _filter.StringMethod = s => s.StartsWith("");
+ ForMember(t=>t.Name).AndValue("Foo").TheResultExpression.ShouldEqual("Invoke(t => t.Name,target).StartsWith(\"Foo\")");
+ }
+ }
+
+ public class BinaryFilterTypeTester : FilterTypeSpec<BinaryFilterType, FilterTestEntity>
+ {
+ [Test]
+ public void BinaryFilterType_should_generate_an_expression_that_calls_the_correct_operator_on_the_value()
+ {
+ _filter.FilterExpressionType = ExpressionType.GreaterThan;
+ ForMember(t => t.Age).AndValue(99).TheResultExpression.ShouldEqual("(Invoke(t => t.Age,target) > 99)");
+ }
+ }
+
+ public class FilterTypeSpec<FILTERTYPE, ENTITYTYPE> where FILTERTYPE : IFilterType, new()
+ {
+ protected FILTERTYPE _filter = new FILTERTYPE();
+ private ConstantExpression _valueExpr;
+ private InvocationExpression _memberAccessExpr;
+
+ public FilterTypeSpec<FILTERTYPE, ENTITYTYPE> ForMember<VALUE>(Expression<Func<ENTITYTYPE, VALUE>> memberExpression)
+ {
+ _memberAccessExpr = Expression.Invoke(memberExpression, Expression.Parameter(typeof(ENTITYTYPE), "target"));
+ return this;
+ }
+
+ public FilterTypeSpec<FILTERTYPE, ENTITYTYPE> AndValue<VALUE>(VALUE value)
+ {
+ _valueExpr = Expression.Constant(value);
+ return this;
+ }
+
+ public string TheResultExpression
+ {
+ get
+ {
+ return _filter.GetExpression(_memberAccessExpr, _valueExpr).ToString();
+ }
+ }
+ }
+
+ public class FilterTestEntity
+ {
+ public string Name { get; set; }
+ public int Age { get; set; }
+ }
+}
View
127 src/FluentNHibernate.Testing/Fixtures.cs
@@ -0,0 +1,127 @@
+using fit;
+using fitlibrary;
+using ShadeTree.DomainModel.Fixtures;
+using ShadeTree.Testing.DomainModel;
+using StoryTeller.FixtureModel;
+using System;
+
+namespace DomainFixtureGeneration
+{
+
+ public partial class CaseFixture : DomainClassFixture<Case>
+ {
+
+ public CaseFixture() : base() { }
+ public CaseFixture(Case subject) : base(subject) { }
+
+
+ [Example("|Number is|[value]|")]
+ public void NumberIs(Int64 propertyValue)
+ {
+ Subject.Number = propertyValue;
+ }
+
+ [Example("|Check|Number|is|[value]|")]
+ public System.Int64 NumberIs()
+ {
+ return Subject.Number;
+ }
+
+
+ [Example("|Name is|[value]|")]
+ public void NameIs(String propertyValue)
+ {
+ Subject.Name = propertyValue;
+ }
+
+ [Example("|Check|Name|is|[value]|")]
+ public System.String NameIs()
+ {
+ return Subject.Name;
+ }
+
+
+ [Example("|Id is|[value]|")]
+ public void IdIs(Int64 propertyValue)
+ {
+ Subject.Id = propertyValue;
+ }
+
+ [Example("|Check|Id|is|[value]|")]
+ public System.Int64 IdIs()
+ {
+ return Subject.Id;
+ }
+
+ }
+
+ public partial class CaseListFixture : DomainListFixture<Case>
+ {
+
+ public CaseListFixture() : base() { }
+ public CaseListFixture(Action<Case[]> doneAction) : base(doneAction) { }
+
+
+ public System.Int64 Number
+ {
+ set
+ {
+ subject.Number = value;
+ }
+ }
+
+ public System.String Name
+ {
+ set
+ {
+ subject.Name = value;
+ }
+ }
+
+ public System.Int64 Id
+ {
+ set
+ {
+ subject.Id = value;
+ }
+ }
+ }
+
+ public partial class ContactFixture : DomainClassFixture<Contact>
+ {
+
+ public ContactFixture() : base() { }
+ public ContactFixture(Contact subject) : base(subject) { }
+
+
+ [Example("|Id is|[value]|")]
+ public void IdIs(Int64 propertyValue)
+ {
+ Subject.Id = propertyValue;
+ }
+
+ [Example("|Check|Id|is|[value]|")]
+ public System.Int64 IdIs()
+ {
+ return Subject.Id;
+ }
+
+ }
+
+ public partial class ContactListFixture : DomainListFixture<Contact>
+ {
+
+ public ContactListFixture() : base() { }
+ public ContactListFixture(Action<Contact[]> doneAction) : base(doneAction) { }
+
+
+ public System.Int64 Id
+ {
+ set
+ {
+ subject.Id = value;
+ }
+ }
+ }
+}
+
View
109 src/FluentNHibernate.Testing/FluentNHibernate.Testing.csproj
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.21022</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F5DC3221-827E-4CB4-B61C-5F50EB4D32EA}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>FluentNHibernate.Testing</RootNamespace>
+ <AssemblyName>FluentNHibernate.Testing</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="fit, Version=1.4.2970.22359, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\tools\fit\fit.dll</HintPath>
+ </Reference>
+ <Reference Include="NHibernate, Version=1.2.1.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\tools\NHibernate\NHibernate.dll</HintPath>
+ </Reference>
+ <Reference Include="NHibernate.Linq, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\tools\NHibernate\NHibernate.Linq.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.framework, Version=2.4.6.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\tools\nunit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="Rhino.Mocks, Version=3.3.0.906, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\tools\rhino\Rhino.Mocks.dll</HintPath>
+ </Reference>
+ <Reference Include="ShadeTree.Core, Version=0.8.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\tools\ShadeTree\ShadeTree.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="StructureMap, Version=2.5.0.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\tools\StructureMap\StructureMap.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\CommonAssemblyInfo.cs">
+ <Link>CommonAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="DomainModel\ConnectedTester.cs" />
+ <Compile Include="DomainModel\EntityEquality.cs" />
+ <Compile Include="DomainModel\Generation\CodeFileSmokeTester.cs" />
+ <Compile Include="DomainModel\InMemoryRepositoryTester.cs" />
+ <Compile Include="DomainModel\Mapping\ClassMapXmlCreationTester.cs" />
+ <Compile Include="DomainModel\Mapping\ConventionsTester.cs" />
+ <Compile Include="DomainModel\Mapping\PropertyMapTester.cs" />
+ <Compile Include="DomainModel\Query\EntityQueryDefinitionTester.cs" />
+ <Compile Include="DomainModel\Query\FilterTypeRegistryTester.cs" />
+ <Compile Include="DomainModel\Query\FilterTypeTester.cs" />
+ <Compile Include="Fixtures.cs" />
+ <Compile Include="SpecificationExtensions.cs" />
+ <Compile Include="Debugging.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="TestUtility.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\FluentNHibernate\FluentNHibernate.csproj">
+ <Project>{1C988DFB-1EC5-484E-87D9-1D3C775BA435}</Project>
+ <Name>ShadeTree.DomainModel</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="DeclarativeTesting.htm" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
8 src/FluentNHibernate.Testing/Properties/AssemblyInfo.cs
@@ -0,0 +1,8 @@
+using System.Reflection;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly : AssemblyTitle("FluentNHibernate.Testing")]
+[assembly : AssemblyDescription("")]
View
205 src/FluentNHibernate.Testing/SpecificationExtensions.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml;
+using NUnit.Framework;
+
+namespace ShadeTree.Testing
+{
+ public delegate void MethodThatThrows();
+
+ public static class SpecificationExtensions
+ {
+ public static void ShouldBeFalse(this bool condition)
+ {
+ Assert.IsFalse(condition);
+ }
+
+ public static void ShouldBeTrue(this bool condition)
+ {
+ Assert.IsTrue(condition);
+ }
+
+ public static object ShouldEqual(this object actual, object expected)
+ {
+ Assert.AreEqual(expected, actual);
+ return expected;
+ }
+
+ public static object ShouldNotEqual(this object actual, object expected)
+ {
+ Assert.AreNotEqual(expected, actual);
+ return expected;
+ }
+
+ public static void ShouldBeNull(this object anObject)
+ {
+ Assert.IsNull(anObject);
+ }
+
+ public static void ShouldNotBeNull(this object anObject)
+ {
+ Assert.IsNotNull(anObject);
+ }
+
+ public static object ShouldBeTheSameAs(this object actual, object expected)
+ {
+ Assert.AreSame(expected, actual);
+ return expected;
+ }
+
+ public static object ShouldNotBeTheSameAs(this object actual, object expected)
+ {
+ Assert.AreNotSame(expected, actual);
+ return expected;
+ }
+
+ public static void ShouldBeOfType(this object actual, Type expected)
+ {
+ Assert.IsInstanceOfType(expected, actual);
+ }
+
+ public static void ShouldNotBeOfType(this object actual, Type expected)
+ {
+ Assert.IsNotInstanceOfType(expected, actual);
+ }
+
+ public static void ShouldContain(this IList actual, object expected)
+ {
+ Assert.Contains(expected, actual);
+ }
+
+ public static void ShouldContain<T>(this IEnumerable<T> actual, T expected)
+ {
+ ShouldContain(actual, x => x.Equals(expected));
+ }
+
+ public static void ShouldContain<T>(this IEnumerable<T> actual, Func<T, bool> expected)
+ {
+ actual.Single(expected).ShouldNotEqual(default(T));
+ }
+
+ public static void ShouldBeEmpty<T>(this IEnumerable<T> actual)
+ {
+ actual.Count().ShouldEqual(0);
+ }
+
+ public static void ShouldHaveCount<T>(this IEnumerable<T> actual, int expected)
+ {
+ actual.Count().ShouldEqual(expected);
+ }
+
+ public static IComparable ShouldBeGreaterThan(this IComparable arg1, IComparable arg2)
+ {
+ Assert.Greater(arg1, arg2);
+ return arg2;
+ }
+
+ public static IComparable ShouldBeLessThan(this IComparable arg1, IComparable arg2)
+ {
+ Assert.Less(arg1, arg2);
+ return arg2;
+ }
+
+ public static void ShouldBeEmpty(this ICollection collection)
+ {
+ Assert.IsEmpty(collection);
+ }
+
+ public static void ShouldBeEmpty(this string aString)
+ {
+ Assert.IsEmpty(aString);
+ }
+
+ public static void ShouldNotBeEmpty(this ICollection collection)
+ {
+ Assert.IsNotEmpty(collection);
+ }
+
+ public static void ShouldNotBeEmpty(this string aString)
+ {
+ Assert.IsNotEmpty(aString);
+ }
+
+ public static void ShouldContain(this string actual, string expected)
+ {
+ StringAssert.Contains(expected, actual);
+ }
+
+ public static string ShouldBeEqualIgnoringCase(this string actual, string expected)
+ {
+ StringAssert.AreEqualIgnoringCase(expected, actual);
+ return expected;
+ }
+
+ public static void ShouldEndWith(this string actual, string expected)
+ {
+ StringAssert.EndsWith(expected, actual);
+ }
+
+ public static void ShouldStartWith(this string actual, string expected)
+ {
+ StringAssert.StartsWith(expected, actual);
+ }
+
+ public static void ShouldContainErrorMessage(this Exception exception, string expected)
+ {
+ StringAssert.Contains(expected, exception.Message);
+ }
+
+ public static Exception ShouldBeThrownBy(this Type exceptionType, MethodThatThrows method)
+ {
+ Exception exception = null;
+
+ try
+ {
+ method();
+ }
+ catch (Exception e)
+ {
+ Assert.AreEqual(exceptionType, e.GetType());
+ exception = e;
+ }
+
+ if (exception == null)
+ {
+ Assert.Fail(String.Format("Expected {0} to be thrown.", exceptionType.FullName));
+ }
+
+ return exception;
+ }
+
+ public static void ShouldEqualSqlDate(this DateTime actual, DateTime expected)
+ {
+ TimeSpan timeSpan = actual - expected;
+ Assert.Less(Math.Abs(timeSpan.TotalMilliseconds), 3);
+ }
+
+ public static object AttributeShouldEqual(this XmlElement element, string attributeName, object expected)
+ {
+ Assert.IsNotNull(element, "The Element is null");
+
+ string actual = element.GetAttribute(attributeName);
+ Assert.AreEqual(expected, actual);
+ return expected;
+ }
+
+ public static XmlElement ShouldHaveChild(this XmlElement element, string xpath)
+ {
+ XmlElement child = element.SelectSingleNode(xpath) as XmlElement;
+ Assert.IsNotNull(child, "Should have a child element matching " + xpath);
+
+ return child;
+ }
+
+ public static XmlElement DoesNotHaveAttribute(this XmlElement element, string attributeName)
+ {
+ Assert.IsNotNull(element, "The Element is null");
+ Assert.IsFalse(element.HasAttribute(attributeName), "Element should not have an attribute named " + attributeName);
+
+ return element;
+ }
+
+ }
+}
View
18 src/FluentNHibernate.Testing/TestUtility.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Reflection;
+
+namespace ShadeTree.Testing
+{
+ public static class TestUtility
+ {
+ public static void FireEvent(object control, string eventName, params object[] args)
+ {
+ MethodInfo minfo =
+ control.GetType().GetMethod("On" + eventName,
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ ParameterInfo[] param = minfo.GetParameters();
+ Type parameterType = param[0].ParameterType;
+ minfo.Invoke(control, new[] {Activator.CreateInstance(parameterType)});
+ }
+ }
+}
View
25 src/FluentNHibernate.sln
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentNHibernate", "FluentNHibernate\FluentNHibernate.csproj", "{1C988DFB-1EC5-484E-87D9-1D3C775BA435}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentNHibernate.Testing", "FluentNHibernate.Testing\FluentNHibernate.Testing.csproj", "{F5DC3221-827E-4CB4-B61C-5F50EB4D32EA}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1C988DFB-1EC5-484E-87D9-1D3C775BA435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1C988DFB-1EC5-484E-87D9-1D3C775BA435}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1C988DFB-1EC5-484E-87D9-1D3C775BA435}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1C988DFB-1EC5-484E-87D9-1D3C775BA435}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F5DC3221-827E-4CB4-B61C-5F50EB4D32EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F5DC3221-827E-4CB4-B61C-5F50EB4D32EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F5DC3221-827E-4CB4-B61C-5F50EB4D32EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F5DC3221-827E-4CB4-B61C-5F50EB4D32EA}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
View
9 src/FluentNHibernate/AssemblyInfo.cs
@@ -0,0 +1,9 @@
+using System.Reflection;
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+
+[assembly : AssemblyTitle("StoryTeller.DomainModel")]
+[assembly : AssemblyDescription("")]
View
96 src/FluentNHibernate/Conventions.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using ShadeTree.Core.Validation;
+using ShadeTree.DomainModel.Mapping;
+using ShadeTree.Validation;
+
+namespace ShadeTree.DomainModel
+{
+ public interface IPropertyConvention
+ {
+ void Process(IProperty property);
+ }
+
+ public class AttributeConvention<T> : IPropertyConvention where T : Attribute
+ {
+ private Action<T, IProperty> _action;
+
+ public AttributeConvention(Action<T, IProperty> action)
+ {
+ _action = action;
+ }
+
+ public void Process(IProperty property)
+ {
+ T att = Attribute.GetCustomAttribute(property.Property, typeof (T), true) as T;
+ if (att != null)
+ {
+ _action(att, property);
+ }
+ }
+ }
+
+ public class Conventions
+ {
+ private readonly List<ITypeConvention> _typeConventions = new List<ITypeConvention>();
+ private List<IPropertyConvention> _propertyConventions = new List<IPropertyConvention>();
+
+ public int DefaultStringLength { get; set; }
+
+ public Conventions()
+ {
+ DefaultStringLength = 100;
+
+ AddTypeConvention(new IgnoreNullableTypeConvention());
+ AddTypeConvention(new EnumerationTypeConvention());
+
+ ForAttribute<RequiredAttribute>((att, prop) =>
+ {
+ if (prop.ParentIsRequired)
+ {
+ prop.SetAttributeOnPropertyElement("not-null", "true");
+ }
+ });
+
+ ForAttribute<MaximumStringLengthAttribute>((att, prop) => prop.SetAttributeOnPropertyElement("length", att.Length.ToString()));
+ ForAttribute<UniqueAttribute>((att, prop) => prop.SetAttributeOnColumnElement("unique", "true"));
+ }
+
+ public Func<PropertyInfo, string> GetForeignKeyName = prop => prop.Name + "_id";
+ public Func<Type, string> GetForeignKeyNameOfParent = type => type.Name + "_id";
+
+ public Func<Type, Type, string> GetManyToManyTableName =
+ (child, parent) => child.Name + "To" + parent.Name;
+
+ public void AddTypeConvention(ITypeConvention convention)
+ {
+ _typeConventions.Add(convention);
+ }
+
+ public ITypeConvention FindConvention(Type propertyType)
+ {
+ var find = _typeConventions.Find(c => c.CanHandle(propertyType));
+ return find ?? new DefaultConvention();
+ }
+
+ public void AlterMap(IProperty property)
+ {
+ if (property.PropertyType == typeof(string))
+ {
+ property.SetAttributeOnPropertyElement("length", DefaultStringLength.ToString());
+ }
+
+ ITypeConvention convention = FindConvention(property.PropertyType);
+ convention.AlterMap(property);
+
+ _propertyConventions.ForEach(c => c.Process(property));
+ }
+
+ public void ForAttribute<T>(Action<T, IProperty> action) where T : Attribute
+ {
+ AttributeConvention<T> convention = new AttributeConvention<T>(action);
+ _propertyConventions.Add(convention);
+ }
+ }
+}
View
41 src/FluentNHibernate/Entity.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace ShadeTree.DomainModel
+{
+ [Serializable]
+ public class Entity : IEquatable<Entity>
+ {
+ public long Id { get; set; }
+
+ public virtual bool Equals(Entity obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (GetType() != obj.GetType()) return false;
+ return obj.Id == Id;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (GetType() != obj.GetType()) return false;
+ return Equals((Entity) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return Id.GetHashCode();
+ }
+
+ public static bool operator ==(Entity left, Entity right)
+ {
+ return Equals(left, right);
+ }
+
+ public static bool operator !=(Entity left, Entity right)
+ {
+ return !Equals(left, right);
+ }
+ }
+}
View
154 src/FluentNHibernate/Fixtures/DomainClassFixture.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using fit;
+using fitlibrary;
+using ShadeTree.Validation;
+using StoryTeller.FixtureModel;
+using ObjectFactory=StructureMap.ObjectFactory;
+
+namespace ShadeTree.DomainModel.Fixtures
+{
+ public class GenericRowFixture<T> : RowFixture where T : class
+ {
+ private T[] _array;
+
+ public GenericRowFixture(T[] array)