Skip to content

Commit 2d7a200

Browse files
committed
Adds test for the issue
1 parent 7d4ade3 commit 2d7a200

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Copyright (C) 2020 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
using System.Transactions;
12+
using NUnit.Framework;
13+
using Xtensive.Core;
14+
using Xtensive.Orm.Configuration;
15+
using Xtensive.Orm.Model;
16+
using Xtensive.Orm.Services;
17+
using Xtensive.Orm.Tests.Issues.IssueGitHub0110_SimpleCommandProcessorOverridesOriginalExceptionModel;
18+
19+
namespace Xtensive.Orm.Tests.Issues.IssueGitHub0110_SimpleCommandProcessorOverridesOriginalExceptionModel
20+
{
21+
[HierarchyRoot(InheritanceSchema.ConcreteTable)]
22+
public class Bin : Entity
23+
{
24+
[Field, Key]
25+
public long Id { get; private set; }
26+
27+
public Bin(Session session)
28+
: base(session)
29+
{
30+
}
31+
}
32+
33+
[HierarchyRoot(InheritanceSchema.ConcreteTable)]
34+
[Index("Name", Unique = true)]
35+
[Index(nameof(Active), nameof(N), nameof(M))]
36+
public class InventoryBalance : Entity
37+
{
38+
[Field, Key]
39+
public long Id { get; private set; }
40+
41+
[Field(Nullable = false)]
42+
public Bin Bin { get; private set; }
43+
44+
[Field]
45+
public bool Active { get; set; }
46+
47+
[Field]
48+
public string Name { get; set; }
49+
50+
[Field]
51+
public decimal N { get; set; }
52+
53+
[Field]
54+
public decimal M { get; set; }
55+
56+
[Field(DefaultSqlExpression = "GETUTCDATE()")]
57+
public DateTime ModifiedOn { get; set; }
58+
59+
public InventoryBalance(Session session, string name, Bin bin)
60+
: base(session)
61+
{
62+
Name = name;
63+
Active = true;
64+
Bin = bin;
65+
}
66+
}
67+
68+
public class OperationState
69+
{
70+
public Exception CatchendException { get; set; }
71+
72+
public bool Ended { get; set; }
73+
74+
public Domain Domain { get; }
75+
76+
public OperationState(Domain domain)
77+
{
78+
Domain = domain;
79+
}
80+
}
81+
}
82+
83+
namespace Xtensive.Orm.Tests.Issues
84+
{
85+
public class IssueGitHub0110_SimpleCommandProcessorOverridesOriginalException : AutoBuildTest
86+
{
87+
protected override void CheckRequirements() => Require.ProviderIs(StorageProvider.SqlServer);
88+
89+
protected override DomainConfiguration BuildConfiguration()
90+
{
91+
var configuration = base.BuildConfiguration();
92+
configuration.Types.Register(typeof(InventoryBalance).Assembly, typeof(InventoryBalance).Namespace);
93+
configuration.UpgradeMode = DomainUpgradeMode.Recreate;
94+
95+
var defaultSessionConfig = configuration.Sessions.Default;
96+
if (defaultSessionConfig == null) {
97+
defaultSessionConfig = new SessionConfiguration(WellKnown.Sessions.Default, SessionOptions.ServerProfile);
98+
configuration.Sessions.Add(defaultSessionConfig);
99+
}
100+
101+
defaultSessionConfig.DefaultIsolationLevel = IsolationLevel.Snapshot;
102+
defaultSessionConfig.DefaultCommandTimeout = 60 * 60; // 60 min.
103+
104+
defaultSessionConfig.BatchSize = 1; //force to use SimpleCommandProcessor
105+
106+
return configuration;
107+
}
108+
109+
protected override void PopulateData()
110+
{
111+
using (var session = Domain.OpenSession())
112+
using (var tx = session.OpenTransaction()) {
113+
_ = new InventoryBalance(session, "aaa", new Bin(session));
114+
tx.Complete();
115+
}
116+
}
117+
118+
[Test]
119+
public void MainTest()
120+
{
121+
var task1State = new OperationState(Domain);
122+
var task2State = new OperationState(Domain);
123+
124+
var task1 = new System.Threading.Tasks.Task(Outer, task1State);
125+
var task2 = new System.Threading.Tasks.Task(Outer, task2State);
126+
task1.Start();
127+
task2.Start();
128+
129+
while (!task1State.Ended && !task1State.Ended) {
130+
Thread.Sleep(100);
131+
}
132+
133+
var exception = task1State.CatchendException ?? task2State.CatchendException;
134+
Assert.That(exception, Is.Not.Null);
135+
Assert.That(exception, Is.InstanceOf<TransactionSerializationFailureException>());
136+
}
137+
138+
private static void Outer(object state)
139+
{
140+
var operationState = (OperationState) state;
141+
try {
142+
using (var session = operationState.Domain.OpenSession(SessionType.User))
143+
using (var tx = session.OpenTransaction()) {
144+
var binId = session.Query.All<Bin>().First().Id;
145+
var bin = session.Query.SingleOrDefault<Bin>(binId);
146+
Inner(session, bin);
147+
tx.Complete();
148+
}
149+
operationState.Ended = true;
150+
}
151+
catch (Exception ex) {
152+
operationState.CatchendException = ex;
153+
operationState.Ended = true;
154+
}
155+
}
156+
157+
private static void Inner(Session session, Bin bin)
158+
{
159+
using (var tx = session.OpenTransaction()) {
160+
var doc = session.Query.All<InventoryBalance>().SingleOrDefault(o => o.Active == true && o.Bin == bin);
161+
doc.N += 1;
162+
tx.Complete();
163+
}
164+
}
165+
}
166+
}

0 commit comments

Comments
 (0)