Рассмотрим код:тест Установка для гонки условия
class TestClass
{
private bool _someFlag;
private object _sharedObject = new object();
private readonly object _syncObject = new object();
public object Read()
{
//lock (_syncObject)
{
_someFlag = false;
return _sharedObject;
}
}
public void Write(object obj)
{
//lock (_syncObject)
{
_someFlag = true;
_sharedObject = obj;
}
}
}
имеет состояние гонки выпуск. Когда мы звоним Read()
, некоторые темы могут звонить Write()
между _someFlag = false;
и return _sharedObject;
строк. Я собираюсь исправить проблему оператором lock
. Но не могли бы вы помочь мне в тестировании этого состояния гонки.
Я не хочу менять _someFlag
на public
для целей тестирования или что-то в этом роде. Я хочу сделать что-то вроде этого:
[Fact]
public void RaceConditionTest()
{
var correctObject = new object();
var test = new TestClass();
for (int i = 0; i < 1000; i++)
{
test.Write(correctObject);
var assertTask = Task.Run(() =>
{
var actualObj = test.Read();
Assert.True(object.ReferenceEquals(correctObject, actualObj), $"Failed on {i} iteration");
});
//Thread.Sleep(50);
var failTask = Task.Run(() => test.Write(new object()));
Task.WaitAll(assertTask, failTask);
}
}
Но как я могу быть уверен, что assertTask
будет запущен до failTask
? Или, может быть, есть еще один способ проверить этот случай? Заранее спасибо.
Условия проведения соревнований, вероятнее всего, невозможно провести единичный тест, как в положительном, так и в особенно отрицательном. Чтобы код надежно выполнял то, что вы не хотите, вам нужно специально установить механизмы синхронизации, которые заставляют операции выполняться в надежном порядке, чтобы вы могли достоверно воспроизвести нежелательное поведение. Но добавить в синхронизацию, чтобы надежно создать нежелательное поведение, которое вы сейчас * заставили * код вести себя неправильно; вы можете так же легко написать, чтобы он вел себя правильно, и если вы не уверены, что у вас есть, вы не можете положиться на тест. – Servy