Skip to content

Commit 4658956

Browse files
David EllingsworthDavid Ellingsworth
authored andcommitted
Add tests for GitHub issue #2552
1 parent 9255435 commit 4658956

File tree

4 files changed

+267
-0
lines changed

4 files changed

+267
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace NHibernate.Test.NHSpecificTest.GH2552
8+
{
9+
public abstract class Details
10+
{
11+
public virtual int Id { get; protected set; }
12+
public virtual Person Person { get; set; }
13+
public virtual string Data { get; set; }
14+
}
15+
public class DetailsByFK : Details { }
16+
public class DetailsByRef : Details { }
17+
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
using System.Reflection;
2+
using NHibernate.Cache;
3+
using NHibernate.Cfg;
4+
using NHibernate.Mapping;
5+
using NHibernate.Test.CacheTest.Caches;
6+
using NUnit.Framework;
7+
8+
namespace NHibernate.Test.NHSpecificTest.GH2552
9+
{
10+
[TestFixture]
11+
public class Fixture : BugTestCase
12+
{
13+
protected override string CacheConcurrencyStrategy => null;
14+
15+
protected override void Configure(Configuration configuration)
16+
{
17+
configuration.SetProperty(Environment.UseSecondLevelCache, "true");
18+
configuration.SetProperty(Environment.UseQueryCache, "true");
19+
configuration.SetProperty(Environment.GenerateStatistics, "true");
20+
configuration.SetProperty(Environment.CacheProvider, typeof(BatchableCacheProvider).AssemblyQualifiedName);
21+
}
22+
23+
protected override void OnSetUp()
24+
{
25+
// Initialize database with data
26+
using (var s = Sfi.OpenSession())
27+
using (var tx =s.BeginTransaction())
28+
{
29+
for (var i = 0; i < 6; i++)
30+
{
31+
var person = new PersonByFK()
32+
{
33+
Name = $"PersonByFK{i}",
34+
Details = (i % 2 == 0)
35+
? new DetailsByFK() { Data = $"DetailsByFK{i}" }
36+
: null,
37+
};
38+
39+
s.Save(person);
40+
}
41+
42+
for (var i = 0; i < 6; i++)
43+
{
44+
var person = new PersonByRef()
45+
{
46+
Name = $"PersonByRef{i}",
47+
Details = (i % 2 == 1)
48+
? new DetailsByRef() { Data = $"DetailsByRef{i}" }
49+
: null,
50+
};
51+
52+
s.Save(person);
53+
}
54+
55+
tx.Commit();
56+
}
57+
}
58+
59+
protected override void OnTearDown()
60+
{
61+
using (var s = OpenSession())
62+
using (var tx = s.BeginTransaction())
63+
{
64+
s.CreateQuery("delete from DetailsByFK").ExecuteUpdate();
65+
s.CreateQuery("delete from PersonByFK").ExecuteUpdate();
66+
s.CreateQuery("delete from DetailsByRef").ExecuteUpdate();
67+
s.CreateQuery("delete from PersonByRef").ExecuteUpdate();
68+
69+
tx.Commit();
70+
}
71+
72+
Sfi.Evict(typeof(PersonByFK));
73+
Sfi.Evict(typeof(DetailsByFK));
74+
Sfi.Evict(typeof(PersonByRef));
75+
Sfi.Evict(typeof(DetailsByRef));
76+
}
77+
78+
private BatchableCache GetDefaultQueryCache()
79+
{
80+
var queryCache = Sfi.GetQueryCache(null);
81+
var field = typeof(StandardQueryCache).GetField(
82+
"_cache",
83+
BindingFlags.NonPublic | BindingFlags.Instance);
84+
Assert.That(field, Is.Not.Null, "Unable to find _cache field");
85+
var cache = (BatchableCache) field.GetValue(queryCache);
86+
Assert.That(cache, Is.Not.Null, "_cache is null");
87+
88+
return cache;
89+
}
90+
91+
private void OneToOneTest<TPerson, TDetails>() where TPerson:Person where TDetails : Details
92+
{
93+
var personPersister = Sfi.GetEntityPersister(typeof(TPerson).FullName);
94+
var detailsPersister = Sfi.GetEntityPersister(typeof(TDetails).FullName);
95+
96+
var personCache = personPersister.Cache.Cache as BatchableCache;
97+
var detailsCache = detailsPersister.Cache.Cache as BatchableCache;
98+
var queryCache = GetDefaultQueryCache();
99+
100+
Assert.That(personCache, Is.Not.Null);
101+
Assert.That(detailsCache, Is.Not.Null);
102+
103+
queryCache.Clear();
104+
personCache.Clear();
105+
detailsCache.Clear();
106+
107+
queryCache.ClearStatistics();
108+
personCache.ClearStatistics();
109+
detailsCache.ClearStatistics();
110+
111+
// Fill the empty caches with data.
112+
using (var s = OpenSession())
113+
using (var tx = s.BeginTransaction())
114+
{
115+
s.QueryOver<TPerson>()
116+
.Cacheable()
117+
.List();
118+
119+
tx.Commit();
120+
}
121+
122+
// Verify query cache statistics
123+
Assert.That(queryCache.PutCalls, Has.Count.EqualTo(1));
124+
Assert.That(queryCache.GetCalls, Has.Count.EqualTo(1));
125+
126+
// Verify person cache statistics
127+
Assert.That(personCache.GetCalls, Has.Count.EqualTo(0));
128+
Assert.That(personCache.PutCalls, Has.Count.EqualTo(0));
129+
Assert.That(personCache.GetMultipleCalls, Has.Count.EqualTo(0));
130+
Assert.That(personCache.PutMultipleCalls, Has.Count.EqualTo(1));
131+
132+
// Verify details cache statistics
133+
Assert.That(detailsCache.GetCalls, Has.Count.EqualTo(0));
134+
Assert.That(detailsCache.PutCalls, Has.Count.EqualTo(3));
135+
Assert.That(detailsCache.GetMultipleCalls, Has.Count.EqualTo(0));
136+
Assert.That(detailsCache.PutMultipleCalls, Has.Count.EqualTo(0));
137+
138+
Sfi.Statistics.Clear();
139+
140+
using (var s = OpenSession())
141+
using (var tx = s.BeginTransaction())
142+
{
143+
s.QueryOver<TPerson>()
144+
.Cacheable()
145+
.List();
146+
147+
tx.Commit();
148+
}
149+
150+
// Verify query cache statistics
151+
Assert.That(queryCache.GetCalls, Has.Count.EqualTo(2));
152+
Assert.That(queryCache.PutCalls, Has.Count.EqualTo(1));
153+
154+
// Verify person cache statistics
155+
Assert.That(personCache.GetCalls, Has.Count.EqualTo(0));
156+
Assert.That(personCache.PutCalls, Has.Count.EqualTo(0));
157+
Assert.That(personCache.GetMultipleCalls, Has.Count.EqualTo(1));
158+
Assert.That(personCache.PutMultipleCalls, Has.Count.EqualTo(1));
159+
160+
// Verify details cache statistics
161+
Assert.That(detailsCache.GetCalls, Has.Count.EqualTo(0));
162+
Assert.That(detailsCache.PutCalls, Has.Count.EqualTo(3));
163+
Assert.That(detailsCache.GetMultipleCalls, Has.Count.EqualTo(1));
164+
Assert.That(detailsCache.PutMultipleCalls, Has.Count.EqualTo(0));
165+
166+
// Verify that no second level cache misses occured.
167+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(0));
168+
Assert.That(Sfi.Statistics.SecondLevelCacheMissCount, Is.EqualTo(0));
169+
}
170+
171+
[Test]
172+
public void OneToOneCacheByForeignKey()
173+
{
174+
OneToOneTest<PersonByFK, DetailsByFK>();
175+
}
176+
177+
[Test]
178+
public void OneToOneCacheByRef()
179+
{
180+
OneToOneTest<PersonByRef, DetailsByRef>();
181+
}
182+
}
183+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.GH2552">
3+
<class name="PersonByFK" batch-size="3">
4+
<cache usage="read-only"/>
5+
<id name="Id" unsaved-value="0" generator="native"/>
6+
<property name="Name"/>
7+
<one-to-one name="Details" class="DetailsByFK" fetch="join" cascade="all"/>
8+
</class>
9+
10+
<class name="DetailsByFK">
11+
<cache usage="read-only"/>
12+
<id name="Id" unsaved-value="0">
13+
<generator class="foreign">
14+
<param name="property">Person</param>
15+
</generator>
16+
</id>
17+
<one-to-one name="Person" class="PersonByFK" constrained="true"/>
18+
<property name="Data"/>
19+
</class>
20+
21+
<class name="PersonByRef" batch-size="3">
22+
<cache usage="read-only"/>
23+
<id name="Id" unsaved-value="0" generator="native"/>
24+
<property name="Name" />
25+
<one-to-one name="Details" class="DetailsByRef" property-ref="Person" fetch="join" cascade="all"/>
26+
</class>
27+
28+
<class name="DetailsByRef">
29+
<cache usage="read-only"/>
30+
<id name="Id" unsaved-value="0" generator="native"/>
31+
<many-to-one name="Person" class="PersonByRef" column="PersonId" unique="true"/>
32+
<property name="Data"/>
33+
</class>
34+
</hibernate-mapping>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using System.Windows.Forms.VisualStyles;
7+
8+
namespace NHibernate.Test.NHSpecificTest.GH2552
9+
{
10+
public abstract class Person
11+
{
12+
private Details _details;
13+
14+
public virtual int Id { get; protected set; }
15+
public virtual string Name { get; set; }
16+
public virtual Details Details {
17+
get => _details;
18+
set
19+
{
20+
_details = value;
21+
22+
if (_details != null)
23+
{
24+
_details.Person = this;
25+
}
26+
}
27+
}
28+
29+
}
30+
public class PersonByFK : Person { }
31+
32+
public class PersonByRef : Person { }
33+
}

0 commit comments

Comments
 (0)