Skip to content

Commit 170e7ab

Browse files
committed
Added a test to validate that doing bad things with transactions and futures does not crash the app
1 parent 357b5df commit 170e7ab

File tree

1 file changed

+126
-1
lines changed

1 file changed

+126
-1
lines changed

FoundationDB.Tests/TransactionFacts.cs

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1923,7 +1923,132 @@ public async Task Test_Simple_Read_Transaction()
19231923

19241924
}
19251925
}
1926-
1926+
1927+
[Test, Category("LongRunning")]
1928+
public async Task Test_BadPractice_Future_Fuzzer()
1929+
{
1930+
const int DURATION_SEC = 30;
1931+
const int R = 100;
1932+
1933+
using (var db = await OpenTestDatabaseAsync())
1934+
{
1935+
var location = db.Partition("Fuzzer");
1936+
1937+
1938+
var rnd = new Random();
1939+
int seed = rnd.Next();
1940+
Log("Using random seeed {0}", seed);
1941+
rnd = new Random(seed);
1942+
1943+
await db.WriteAsync((tr) =>
1944+
{
1945+
for (int i = 0; i < R; i++)
1946+
{
1947+
tr.Set(location.Pack(i), Slice.FromInt32(i));
1948+
}
1949+
}, this.Cancellation);
1950+
1951+
var start = DateTime.UtcNow;
1952+
Log("This test will run for {0} seconds", DURATION_SEC);
1953+
1954+
int time = 0;
1955+
1956+
List<IFdbTransaction> m_alive = new List<IFdbTransaction>();
1957+
while (DateTime.UtcNow - start < TimeSpan.FromSeconds(DURATION_SEC))
1958+
{
1959+
switch (rnd.Next(10))
1960+
{
1961+
case 0:
1962+
{ // start a new transaction
1963+
Console.Write('T');
1964+
var tr = db.BeginTransaction(FdbTransactionMode.Default, this.Cancellation);
1965+
m_alive.Add(tr);
1966+
break;
1967+
}
1968+
case 1:
1969+
{ // drop a random transaction
1970+
if (m_alive.Count == 0) continue;
1971+
Console.Write('L');
1972+
int p = rnd.Next(m_alive.Count);
1973+
1974+
m_alive.RemoveAt(p);
1975+
//no dispose
1976+
break;
1977+
}
1978+
case 2:
1979+
{ // dispose a random transaction
1980+
if (m_alive.Count == 0) continue;
1981+
Console.Write('D');
1982+
int p = rnd.Next(m_alive.Count);
1983+
1984+
var tr = m_alive[p];
1985+
tr.Dispose();
1986+
m_alive.RemoveAt(p);
1987+
break;
1988+
}
1989+
case 3:
1990+
{ // GC!
1991+
Console.Write('C');
1992+
var tr = db.BeginTransaction(FdbTransactionMode.ReadOnly, this.Cancellation);
1993+
m_alive.Add(tr);
1994+
await tr.GetReadVersionAsync();
1995+
break;
1996+
}
1997+
1998+
case 4:
1999+
case 5:
2000+
case 6:
2001+
{ // read a random value from a random transaction
2002+
Console.Write('G');
2003+
if (m_alive.Count == 0) break;
2004+
int p = rnd.Next(m_alive.Count);
2005+
var tr = m_alive[p];
2006+
2007+
int x = rnd.Next(R);
2008+
try
2009+
{
2010+
var res = await tr.GetAsync(location.Pack(x));
2011+
}
2012+
catch (FdbException)
2013+
{
2014+
Console.Write('!');
2015+
}
2016+
break;
2017+
}
2018+
case 7:
2019+
case 8:
2020+
case 9:
2021+
{ // read a random value, but drop the task
2022+
Console.Write('g');
2023+
if (m_alive.Count == 0) break;
2024+
int p = rnd.Next(m_alive.Count);
2025+
var tr = m_alive[p];
2026+
2027+
int x = rnd.Next(R);
2028+
var t = tr.GetAsync(location.Pack(x)).ContinueWith((_) => Console.Write('!'), TaskContinuationOptions.NotOnRanToCompletion);
2029+
// => t is not stored
2030+
break;
2031+
}
2032+
2033+
}
2034+
if ((time++) % 80 == 0)
2035+
{
2036+
Console.WriteLine();
2037+
Log("State: {0}", m_alive.Count);
2038+
Console.Write('C');
2039+
GC.Collect();
2040+
GC.WaitForPendingFinalizers();
2041+
GC.Collect();
2042+
}
2043+
2044+
}
2045+
2046+
GC.Collect();
2047+
GC.WaitForPendingFinalizers();
2048+
GC.Collect();
2049+
}
2050+
2051+
}
19272052
}
19282053

19292054
}

0 commit comments

Comments
 (0)