Skip to content

Commit ef0b34f

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

File tree

4 files changed

+253
-0
lines changed

4 files changed

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

0 commit comments

Comments
 (0)