|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Technewlogic.Stasy.Test.Model;
using Technewlogic.Stasy.Framework.Proxy;
using Technewlogic.Stasy.Framework;
using System.Threading;
using Technewlogic.Stasy.Framework.Transactions;
using Technewlogic.Stasy.Framework.UnitOfWork;
namespace Technewlogic.Stasy.Test.TransactionTests
{
[TestFixture]
public class Concurrency
{
private Engine<CrmContext> _engine;
private CrmContext _context;
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
}
[SetUp]
public void SetUp()
{
_context = new CrmContext();
_engine = EngineFactory.CreateEngine(
new DataContextMockSyncProvider(new DataContextMock()),
_context);
}
/// <summary>
/// Having 2 parallel transactions modifying 2 independent values is allowed.
/// </summary>
[Test]
public void Concurrency_WriteIndependentObjects()
{
Customer sundk = _context.Customers.Single(c => c.Name == Customer.SKName);
Customer pizzaExpress = _context.Customers.Single(c => c.Name == Customer.PizzaInderName);
AutoResetEvent evt1 = new AutoResetEvent(false);
AutoResetEvent evt2 = new AutoResetEvent(false);
AutoResetEvent evt3 = new AutoResetEvent(false);
AutoResetEvent endOfB = new AutoResetEvent(false);
Action a = () =>
{
_engine.TransactionManager.ExecuteTransaction(() =>
{
sundk.AccountNumber = 987;
// start the other thread
evt1.Set();
// the other thread should read the "original" value...
evt2.WaitOne();
evt3.Set();
// the other thread should read the committed value
Console.WriteLine("End Thread A");
});
};
Action b = () =>
{
_engine.TransactionManager.ExecuteTransaction(() =>
{
// wait for the other thread to change the value
evt1.WaitOne();
pizzaExpress.AccountNumber = 456;
evt2.Set();
// let the other thread continue and commit
evt3.WaitOne();
endOfB.Set();
});
};
a.BeginInvoke(null, null);
b.BeginInvoke(null, null);
if (!endOfB.WaitOne(2000, false))
throw new Exception("Exception in Thread (see exception list)");
Assert.AreEqual(987, sundk.AccountNumber);
Assert.AreEqual(456, pizzaExpress.AccountNumber);
Console.WriteLine("End Main Thread");
}
// IMP: Mehr UseCases überlegen
/// <summary>
/// Trying to write an entity if it is was already written in another transaction which is still running is forbidden.
/// The committed value is the one from the earlier transaction.
/// </summary>
[Test]
public void Concurrency_WriteSame()
{
throw new NotImplementedException();
//Customer sundk = _context.Customers.Single(c => c.Name == Customer.SKName);
//AutoResetEvent evt1 = new AutoResetEvent(false);
//AutoResetEvent evt2 = new AutoResetEvent(false);
//AutoResetEvent evt3 = new AutoResetEvent(false);
//AutoResetEvent endOfB = new AutoResetEvent(false);
//bool exceptionThrown = false;
//Action a = () =>
//{
// using (var t_a = _engine.TransactionManager.BeginTransaction())
// {
// sundk.AccountNumber = 987;
// // start the other thread
// evt1.Set();
// // the other thread should read the "original" value...
// evt2.WaitOne();
// evt3.Set();
// // the other thread should read the committed value
// Console.WriteLine("End Thread A");
// }
//};
//Action b = () =>
//{
// try
// {
// using (var t_b = _engine.TransactionManager.BeginTransaction())
// {
// // wait for the other thread to change the value
// evt1.WaitOne();
// sundk.AccountNumber = 456;
// }
// }
// catch (ConcurrencyException)
// {
// exceptionThrown = true;
// }
// evt2.Set();
// // let the other thread continue and commit
// evt3.WaitOne();
// endOfB.Set();
//};
//a.BeginInvoke(null, null);
//b.BeginInvoke(null, null);
//if (!endOfB.WaitOne(2000, false))
// throw new Exception("Exception in Thread (see exception list)");
//Assert.AreEqual(987, sundk.AccountNumber);
//Assert.AreEqual(true, exceptionThrown);
//Console.WriteLine("End Main Thread");
}
[Test]
public void Concurrency_WriteSameRetry()
{
throw new NotImplementedException();
//Customer sundk = _context.Customers.Single(c => c.Name == Customer.SKName);
//AutoResetEvent evt1 = new AutoResetEvent(false);
//AutoResetEvent endOfB = new AutoResetEvent(false);
//Action a = () =>
//{
// using (var t_a = _engine.TransactionManager.BeginTransaction())
// {
// Console.WriteLine("Start Thread A");
// sundk.AccountNumber = 987;
// // start the other thread
// evt1.Set();
// Console.WriteLine("Thread A is sleeping (doing some work ;) )");
// Thread.Sleep(2000);
// Console.WriteLine("End Thread A");
// }
//};
//Action b = () =>
//{
// // wait for the other thread to change the value
// evt1.WaitOne();
// _engine.TransactionManager.ExecuteTransaction(() =>
// {
// Console.WriteLine("Thread B Trying");
// sundk.AccountNumber = 456;
// Console.WriteLine("End Thread B");
// endOfB.Set();
// }, 1);
//};
//a.BeginInvoke(null, null);
//b.BeginInvoke(null, null);
//if (!endOfB.WaitOne(4000, false))
// throw new Exception("Exception in Thread (see exception list)");
//Assert.AreEqual(456, sundk.AccountNumber);
//Console.WriteLine("End Main Thread");
}
[Test]
public void Concurrency_ExecuteTransaction_AutoRollback()
{
throw new NotImplementedException();
//Customer sundk = _context.Customers.Single(c => c.Name == Customer.SKName);
//Customer pizzaExpress = _context.Customers.Single(c => c.Name == Customer.PizzaInderName);
//var originalPizzaAccout = pizzaExpress.AccountNumber;
//AutoResetEvent evt1 = new AutoResetEvent(false);
//AutoResetEvent evt2 = new AutoResetEvent(false);
//AutoResetEvent evt3 = new AutoResetEvent(false);
//AutoResetEvent endOfB = new AutoResetEvent(false);
//Action a = () =>
//{
// using (var t_a = _engine.TransactionManager.BeginTransaction())
// {
// Console.WriteLine("Start Thread A");
// sundk.AccountNumber = 987;
// // start the other thread
// evt1.Set();
// Console.WriteLine("Thread A is sleeping (doing some work ;) )");
// Thread.Sleep(2000);
// Console.WriteLine("End Thread A");
// }
//};
//Action b = () =>
//{
// // wait for the other thread to change the value
// evt1.WaitOne();
// try
// {
// _engine.TransactionManager.ExecuteTransaction(() =>
// {
// Console.WriteLine("Thread B Trying");
// pizzaExpress.AccountNumber = 888;
// sundk.AccountNumber = 456;
// Console.WriteLine("End Thread B");
// });
// }
// catch (ConcurrencyException)
// {
// Console.WriteLine("Exception Thread B");
// endOfB.Set();
// }
//};
//a.BeginInvoke(null, null);
//b.BeginInvoke(null, null);
//if (!endOfB.WaitOne(4000, false))
// throw new Exception("Exception in Thread (see exception list)");
//Assert.AreEqual(originalPizzaAccout, pizzaExpress.AccountNumber);
//Console.WriteLine("End Main Thread");
}
// TODO: ExecuteTransaction
// TODO: Mehrere Transaktionen nacheinander
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.