diff --git a/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/Context.cs b/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/Context.cs index 207d16cbf2..b1d5daed66 100644 --- a/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/Context.cs +++ b/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/Context.cs @@ -12,18 +12,50 @@ namespace Xtensive.Orm.Reprocessing.Tests.ReprocessingContext { - public class Context + public class Context : IDisposable { private readonly Domain domain; + public int Count; private AutoResetEvent wait1 = new AutoResetEvent(false); private AutoResetEvent wait2 = new AutoResetEvent(false); - public void Deadlock(bool first, IsolationLevel? isolationLevel, TransactionOpenMode? transactionOpenMode) + public bool Disposed { get; private set; } + + /// + /// Root runner. + /// + public void Run( + IsolationLevel? isolationLevel, + TransactionOpenMode? transactionOpenMode, + Action action) { - TestContext.WriteLine("Context.DeadLock entered"); - domain.WithStrategy(ExecuteActionStrategy.HandleUniqueConstraintViolation).WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)).WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)).Execute( + domain.Execute( session => { + session.Remove(session.Query.All()); + session.Remove(session.Query.All()); + session.Remove(session.Query.All()); + _ = new Bar(session); + _ = new Foo(session); + }); + + Parallel.Invoke( + () => action(true, isolationLevel, transactionOpenMode), + () => action(false, isolationLevel, transactionOpenMode)); + } + + #region Actions + + // The actions that can be passed to root runner method (Run) + // Some might be wrapped by other actons, + // others used only directrly from runner method + + public void Deadlock(bool first, IsolationLevel? isolationLevel, TransactionOpenMode? transactionOpenMode) + { + domain.WithStrategy(ExecuteActionStrategy.HandleUniqueConstraintViolation) + .WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)) + .WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)) + .Execute(session => { _ = Interlocked.Increment(ref Count); _ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() }; if (first) { @@ -31,6 +63,7 @@ public void Deadlock(bool first, IsolationLevel? isolationLevel, TransactionOpen if (wait1 != null) { _ = wait1.Set(); _ = wait2.WaitOne(); + wait1.Dispose(); wait1 = null; } _ = session.Query.All().Lock(LockMode.Exclusive, LockBehavior.Wait).ToArray(); @@ -40,12 +73,12 @@ public void Deadlock(bool first, IsolationLevel? isolationLevel, TransactionOpen if (wait2 != null) { _ = wait2.Set(); _ = wait1.WaitOne(); + wait2.Dispose(); wait2 = null; } _ = session.Query.All().Lock(LockMode.Exclusive, LockBehavior.Wait).ToArray(); } }); - TestContext.WriteLine("Context.DeadLock left"); } public void External( @@ -54,7 +87,6 @@ public void External( TransactionOpenMode? transactionOpenMode, Action action) { - TestContext.WriteLine("Context.External entered"); using (var session = domain.OpenSession()) using (var tran = isolationLevel == null ? null : session.OpenTransaction()) { if (tran != null) { @@ -76,7 +108,6 @@ public void External( tran.Complete(); } } - TestContext.WriteLine("Context.External left"); } public void Parent( @@ -86,7 +117,6 @@ public void Parent( IExecuteActionStrategy strategy, Action action) { - TestContext.WriteLine("Context.Parent1 entered"); domain.WithStrategy(strategy) .WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)) .WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)) @@ -106,7 +136,6 @@ public void Parent( } action(first, isolationLevel, transactionOpenMode); }); - TestContext.WriteLine("Context.Parent1 left"); } public void Parent( @@ -117,7 +146,6 @@ public void Parent( IExecuteActionStrategy strategy, Action action) { - TestContext.WriteLine("Context.Parent2 entered"); domain.WithStrategy(strategy) .WithSession(session) .WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)) @@ -138,38 +166,15 @@ public void Parent( } action(first, isolationLevel, transactionOpenMode); }); - TestContext.WriteLine("Context.Parent2 left"); - } - - public void Run( - IsolationLevel? isolationLevel, - TransactionOpenMode? transactionOpenMode, - Action action) - { - TestContext.WriteLine("Context.Run entered"); - domain.Execute( - session => { - session.Remove(session.Query.All()); - session.Remove(session.Query.All()); - session.Remove(session.Query.All()); - _ = new Bar(session); - _ = new Foo(session); - }); - TestContext.WriteLine("Context.Run executed Domain.Execute"); - TestContext.WriteLine("Context.Run Parallel.Invoke started"); - Parallel.Invoke( - () => action(true, isolationLevel, transactionOpenMode), - () => action(false, isolationLevel, transactionOpenMode)); - TestContext.WriteLine("Context.Run Parallel.Invoke ended"); - TestContext.WriteLine("Context.Run left"); } public void UniqueConstraintViolation( bool first, IsolationLevel? isolationLevel, TransactionOpenMode? transactionOpenMode) { - TestContext.WriteLine("Context.UniqueConstraintViolation entered"); - domain.WithStrategy(ExecuteActionStrategy.HandleUniqueConstraintViolation).WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)).WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)).Execute( - session => { + domain.WithStrategy(ExecuteActionStrategy.HandleUniqueConstraintViolation) + .WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)) + .WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)) + .Execute(session => { _ = Interlocked.Increment(ref Count); session.EnsureTransactionIsStarted(); _ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() }; @@ -179,27 +184,29 @@ public void UniqueConstraintViolation( if (wait1 != null && wait2 != null) { _ = wait1.Set(); _ = wait2.WaitOne(); + wait1.Dispose(); wait1 = null; } } else if (wait2 != null && wait2 != null) { _ = wait2.Set(); _ = wait1.WaitOne(); + wait2.Dispose(); wait2 = null; } _ = new Foo(session) { Name = name }; } session.SaveChanges(); }); - TestContext.WriteLine("Context.UniqueConstraintViolation left"); } public void UniqueConstraintViolationPrimaryKey( bool first, IsolationLevel? isolationLevel, TransactionOpenMode? transactionOpenMode) { - TestContext.WriteLine("Context.UniqueConstraintViolationPrimaryKey entered"); - domain.WithStrategy(ExecuteActionStrategy.HandleUniqueConstraintViolation).WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)).WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)).Execute( - session => { + domain.WithStrategy(ExecuteActionStrategy.HandleUniqueConstraintViolation) + .WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)) + .WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)) + .Execute(session => { _ = Interlocked.Increment(ref Count); session.EnsureTransactionIsStarted(); _ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() }; @@ -211,25 +218,36 @@ public void UniqueConstraintViolationPrimaryKey( if (w1 != null && w2 != null) { _ = w1.Set(); _ = w2.WaitOne(); + wait1.Dispose(); wait1 = null; } } else if (w1 != null && w2 != null) { _ = w2.Set(); _ = w1.WaitOne(); + wait2.Dispose(); wait2 = null; } _ = new Foo(session, id) { Name = Guid.NewGuid().ToString() }; } session.SaveChanges(); }); - TestContext.WriteLine("Context.UniqueConstraintViolationPrimaryKey left"); } + #endregion public Context(Domain domain) { this.domain = domain; } + + public void Dispose() + { + if (Disposed) + return; + Disposed = true; + wait1?.Dispose(); + wait2?.Dispose(); + } } } diff --git a/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/DeadlockReprocessing.cs b/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/DeadlockReprocessing.cs index f0f186c873..66f01d2bb5 100644 --- a/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/DeadlockReprocessing.cs +++ b/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/DeadlockReprocessing.cs @@ -10,77 +10,77 @@ using NUnit.Framework; using TestCommon.Model; using Xtensive.Orm.Reprocessing.Tests.ReprocessingContext; +using Xtensive.Orm.Tests; namespace Xtensive.Orm.Reprocessing.Tests { - [TestFixture, Timeout(DefaultTestTimeout * 4)] + [TestFixture] public class DeadlockReprocessing : ReprocessingBaseTest { + protected override void CheckRequirements() + { + base.CheckRequirements(); + Require.ProviderIsNot(StorageProvider.Firebird, "Throws timeout operation instead of deadlock, which is not reprocessible."); + } + [Test, Timeout(DefaultTestTimeout)] public void SimpleDeadlockTest() { - Console.WriteLine("Test started"); - - var context = new Context(Domain); - context.Run(IsolationLevel.Serializable, null, context.Deadlock); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(2)); + using (var context = new Context(Domain)) { + context.Run(IsolationLevel.Serializable, null, context.Deadlock); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(2)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSerializableDeadlockTest() { - Console.WriteLine("Test started"); - - var context = new Context(Domain); - context.Run( - IsolationLevel.Serializable, - null, - (b, level, open) => context.Parent(b, level, open, ExecuteActionStrategy.HandleReprocessableException, context.Deadlock)); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Serializable, + null, + (b, level, open) => context.Parent(b, level, open, ExecuteActionStrategy.HandleReprocessableException, context.Deadlock)); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSnapshotDeadlockTest() { - Console.WriteLine("Test started"); - - var context = new Context(Domain); - context.Run( - IsolationLevel.Snapshot, - null, - (b, level, open) => context.Parent(b, level, open, ExecuteActionStrategy.HandleReprocessableException, context.Deadlock)); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Snapshot, + null, + (b, level, open) => context.Parent(b, level, open, ExecuteActionStrategy.HandleReprocessableException, context.Deadlock)); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedNestedSerializableSerializableTest() { - Console.WriteLine("Test started"); - //nested nested serializable deadlock - var context = new Context(Domain); - context.Run( - IsolationLevel.Serializable, - null, - (b, level, open) => - context.Parent( - b, - level, - open, - ExecuteActionStrategy.HandleReprocessableException, - (b1, level1, open1) => - context.Parent(b1, level1, open1, ExecuteActionStrategy.HandleReprocessableException, context.Deadlock))); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(6)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Serializable, + null, + (b, level, open) => + context.Parent( + b, + level, + open, + ExecuteActionStrategy.HandleReprocessableException, + (b1, level1, open1) => + context.Parent(b1, level1, open1, ExecuteActionStrategy.HandleReprocessableException, context.Deadlock))); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(6)); + } } - private int Bar2Count() - { - return Domain.Execute(session => session.Query.All().Count()); - } + private int Bar2Count() => Domain.Execute(session => session.Query.All().Count()); } } diff --git a/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/UniqueConstraintViolationReprocessing.cs b/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/UniqueConstraintViolationReprocessing.cs index c901fa1812..589534aa35 100644 --- a/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/UniqueConstraintViolationReprocessing.cs +++ b/Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/UniqueConstraintViolationReprocessing.cs @@ -25,12 +25,11 @@ public override void TestFixtureSetUp() [Test, Timeout(DefaultTestTimeout)] public void SimpleUniqueTest() { - Console.WriteLine("Test started"); - - var context = new Context(Domain); - context.Run(null, null, context.UniqueConstraintViolation); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(2)); + using (var context = new Context(Domain)) { + context.Run(null, null, context.UniqueConstraintViolation); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(2)); + } } [Test, Timeout(DefaultTestTimeout)] @@ -74,189 +73,180 @@ public void UniqueConstraintViolationExceptionPrimary() [Test, Timeout(DefaultTestTimeout)] public void NestedSerializablePrimaryKeyConstraintTest() { - Console.WriteLine("Test started"); - - var context = new Context(Domain); - context.Run( - IsolationLevel.Serializable, - null, - (b, level, open) => - context.Parent( - b, level, open, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolationPrimaryKey)); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Serializable, + null, + (b, level, open) => + context.Parent( + b, level, open, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolationPrimaryKey)); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSnapshotPrimaryKeyConstraintTest() { - Console.WriteLine("Test started"); - - var context = new Context(Domain); - context.Run( - IsolationLevel.Snapshot, - null, - (b, level, open) => - context.Parent( - b, level, open, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolationPrimaryKey)); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Snapshot, + null, + (b, level, open) => + context.Parent( + b, level, open, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolationPrimaryKey)); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSerializableUniqueIndexTest() { - Console.WriteLine("Test started"); - - var context = new Context(Domain); - context.Run( - IsolationLevel.Serializable, - null, - (b, level, open) => - context.Parent( - b, level, null, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolation)); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Serializable, + null, + (b, level, open) => + context.Parent( + b, level, null, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolation)); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSnapshotUniqueIndexTest() { - Console.WriteLine("Test started"); - - var context = new Context(Domain); - context.Run( - IsolationLevel.Snapshot, - null, - (b, level, open) => - context.Parent( - b, level, null, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolation)); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Snapshot, + null, + (b, level, open) => + context.Parent( + b, level, null, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolation)); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSerializableExternalWithoutTxUniqueIndexTest() { - Console.WriteLine("Test started"); - //ExternalWithoutTransaction nested serializable UniqueConstraint - var context = new Context(Domain); - context.Run( - IsolationLevel.Serializable, - null, - (b, level, open) => - context.External( - b, - null, - open, - (s, b1, level1, open1) => - context.Parent( - s, - b1, - IsolationLevel.Serializable, - open1, - ExecuteActionStrategy.HandleUniqueConstraintViolation, - context.UniqueConstraintViolation))); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Serializable, + null, + (b, level, open) => + context.External( + b, + null, + open, + (s, b1, level1, open1) => + context.Parent( + s, + b1, + IsolationLevel.Serializable, + open1, + ExecuteActionStrategy.HandleUniqueConstraintViolation, + context.UniqueConstraintViolation))); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSnapshotExternalWithoutTxUniqueIndexTest() { - Console.WriteLine("Test started"); - //ExternalWithoutTransaction nested snapshot UniqueConstraint - var context = new Context(Domain); - context.Run( - IsolationLevel.Snapshot, - null, - (b, level, open) => - context.External( - b, - null, - open, - (s, b1, level1, open1) => - context.Parent( - s, - b1, - IsolationLevel.Snapshot, - open1, - ExecuteActionStrategy.HandleUniqueConstraintViolation, - context.UniqueConstraintViolation))); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Snapshot, + null, + (b, level, open) => + context.External( + b, + null, + open, + (s, b1, level1, open1) => + context.Parent( + s, + b1, + IsolationLevel.Snapshot, + open1, + ExecuteActionStrategy.HandleUniqueConstraintViolation, + context.UniqueConstraintViolation))); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSerializableExternalWithTxUniqueIndexTest() { - Console.WriteLine("Test started"); - //ExternalWithTransaction nested serializable UniqueConstraint - var context = new Context(Domain); - context.Run( - IsolationLevel.Serializable, - null, - (b, level, open) => - context.External( - b, - level, - open, - (s, b1, level1, open1) => - context.Parent( - s, - b1, - level1, - open1, - ExecuteActionStrategy.HandleUniqueConstraintViolation, - context.UniqueConstraintViolation))); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(6)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Serializable, + null, + (b, level, open) => + context.External( + b, + level, + open, + (s, b1, level1, open1) => + context.Parent( + s, + b1, + level1, + open1, + ExecuteActionStrategy.HandleUniqueConstraintViolation, + context.UniqueConstraintViolation))); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(6)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedSnapshotExternalWithTxUniqueIndexTest() { - Console.WriteLine("Test started"); - //ExternalWithTransaction nested snapshot UniqueConstraint - var context = new Context(Domain); - context.Run( - IsolationLevel.Snapshot, - null, - (b, level, open) => - context.External( - b, - level, - open, - (s, b1, level1, open1) => - context.Parent( - s, - b1, - level1, - open1, - ExecuteActionStrategy.HandleUniqueConstraintViolation, - context.UniqueConstraintViolation))); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(6)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.Snapshot, + null, + (b, level, open) => + context.External( + b, + level, + open, + (s, b1, level1, open1) => + context.Parent( + s, + b1, + level1, + open1, + ExecuteActionStrategy.HandleUniqueConstraintViolation, + context.UniqueConstraintViolation))); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(6)); + } } [Test, Timeout(DefaultTestTimeout)] public void NestedUniqueIndexWithAutoTransaction() { - Console.WriteLine("Test started"); - //nested UniqueConstraint with auto transaction - var context = new Context(Domain); - context.Run( - IsolationLevel.ReadUncommitted, - TransactionOpenMode.Auto, - (b, l, o) => - context.Parent(b, l, o, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolation)); - Assert.That(context.Count, Is.EqualTo(3)); - Assert.That(Bar2Count(), Is.EqualTo(4)); + using (var context = new Context(Domain)) { + context.Run( + IsolationLevel.ReadUncommitted, + TransactionOpenMode.Auto, + (b, l, o) => + context.Parent(b, l, o, ExecuteActionStrategy.HandleUniqueConstraintViolation, context.UniqueConstraintViolation)); + Assert.That(context.Count, Is.EqualTo(3)); + Assert.That(Bar2Count(), Is.EqualTo(4)); + } } private int Bar2Count()