2023-03-17 23:06:47 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "API.h"
|
2023-03-20 17:13:55 -04:00
|
|
|
#include "Catch2Includes.h"
|
2023-03-17 23:06:47 -04:00
|
|
|
|
|
|
|
|
#include <AutoRTFM/AutoRTFM.h>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <thread>
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.autortfm_is_transactional")
|
|
|
|
|
{
|
|
|
|
|
REQUIRE(false == autortfm_is_transactional());
|
|
|
|
|
|
|
|
|
|
bool InTransaction = false;
|
|
|
|
|
bool InOpenNest = false;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
InTransaction = autortfm_is_transactional();
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
InOpenNest = autortfm_is_transactional();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == InTransaction);
|
|
|
|
|
REQUIRE(true == InOpenNest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.autortfm_is_closed")
|
|
|
|
|
{
|
|
|
|
|
REQUIRE(false == autortfm_is_closed());
|
|
|
|
|
|
|
|
|
|
// Set to the opposite of what we expect at the end of function.
|
|
|
|
|
bool InTransaction = false;
|
|
|
|
|
bool InOpenNest = true;
|
|
|
|
|
bool InClosedNestInOpenNest = false;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
InTransaction = autortfm_is_closed();
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
InOpenNest = autortfm_is_closed();
|
|
|
|
|
|
2023-03-24 18:18:15 -04:00
|
|
|
REQUIRE(AutoRTFM::EContextStatus::OnTrack == AutoRTFM::Close([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InClosedNestInOpenNest = autortfm_is_closed();
|
2023-03-24 18:18:15 -04:00
|
|
|
}));
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == InTransaction);
|
|
|
|
|
REQUIRE(false == InOpenNest);
|
|
|
|
|
REQUIRE(true == InClosedNestInOpenNest);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-24 12:04:10 -04:00
|
|
|
TEST_CASE("API.autortfm_abort_transaction")
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
bool BeforeNest = false;
|
|
|
|
|
bool InNest = false;
|
|
|
|
|
bool AfterNest = false;
|
|
|
|
|
AutoRTFM::ETransactionResult NestResult;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
BeforeNest = true;
|
|
|
|
|
|
|
|
|
|
NestResult = AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
// Because we are aborting this won't actually occur!
|
|
|
|
|
InNest = true;
|
|
|
|
|
|
2023-03-22 19:46:30 -04:00
|
|
|
autortfm_abort_transaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AfterNest = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == BeforeNest);
|
|
|
|
|
REQUIRE(false == InNest);
|
|
|
|
|
REQUIRE(true == AfterNest);
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == NestResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.autortfm_abort_if_transactional")
|
|
|
|
|
{
|
|
|
|
|
// Calling this outwith any transaction won't abort the program.
|
|
|
|
|
autortfm_abort_if_transactional();
|
|
|
|
|
|
|
|
|
|
bool BeforeNest = false;
|
|
|
|
|
bool InNest = false;
|
|
|
|
|
bool AfterNest = false;
|
|
|
|
|
AutoRTFM::ETransactionResult NestResult;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
BeforeNest = true;
|
|
|
|
|
|
|
|
|
|
NestResult = AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
// Because we are aborting this won't actually occur!
|
|
|
|
|
InNest = true;
|
|
|
|
|
|
|
|
|
|
autortfm_abort_if_transactional();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AfterNest = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == BeforeNest);
|
|
|
|
|
REQUIRE(false == InNest);
|
|
|
|
|
REQUIRE(true == AfterNest);
|
2023-05-11 05:22:24 -04:00
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == NestResult);
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.autortfm_abort_if_closed")
|
|
|
|
|
{
|
|
|
|
|
// Calling this outwith any transaction won't abort the program.
|
|
|
|
|
autortfm_abort_if_closed();
|
|
|
|
|
|
|
|
|
|
bool BeforeNest = false;
|
|
|
|
|
bool InNest = false;
|
|
|
|
|
bool AfterNest = false;
|
|
|
|
|
|
2023-05-11 05:22:24 -04:00
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == AutoRTFM::Transact([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
BeforeNest = true;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
InNest = true;
|
|
|
|
|
|
|
|
|
|
// This won't abort because we aren't closed!
|
|
|
|
|
autortfm_abort_if_closed();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AfterNest = true;
|
|
|
|
|
|
|
|
|
|
autortfm_abort_if_closed();
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(false == BeforeNest);
|
|
|
|
|
REQUIRE(true == InNest);
|
|
|
|
|
REQUIRE(false == AfterNest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.autortfm_open")
|
|
|
|
|
{
|
|
|
|
|
int Answer = 6 * 9;
|
|
|
|
|
|
|
|
|
|
// An open call outside a transaction succeeds.
|
|
|
|
|
autortfm_open([](void* const Arg)
|
|
|
|
|
{
|
|
|
|
|
*static_cast<int* const>(Arg) = 42;
|
|
|
|
|
}, &Answer);
|
|
|
|
|
|
|
|
|
|
REQUIRE(42 == Answer);
|
|
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
// An open call inside a transaction succeeds also.
|
|
|
|
|
autortfm_open([](void* const Arg)
|
|
|
|
|
{
|
|
|
|
|
*static_cast<int* const>(Arg) *= 2;
|
|
|
|
|
}, &Answer);
|
|
|
|
|
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(84 == Answer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.autortfm_register_open_function")
|
|
|
|
|
{
|
|
|
|
|
autortfm_register_open_function(
|
|
|
|
|
reinterpret_cast<void*>(NoAutoRTFM::DoSomethingC),
|
|
|
|
|
reinterpret_cast<void*>(NoAutoRTFM::DoSomethingInTransactionC));
|
|
|
|
|
|
|
|
|
|
int I = -42;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
I = NoAutoRTFM::DoSomethingC(I);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(0 == I);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 05:11:46 -05:00
|
|
|
TEST_CASE("API.autortfm_on_commit")
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
bool OuterTransaction = false;
|
|
|
|
|
bool InnerTransaction = false;
|
|
|
|
|
bool InnerTransactionWithAbort = false;
|
|
|
|
|
bool InnerOpenNest = false;
|
|
|
|
|
AutoRTFM::ETransactionResult NestResult;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
autortfm_on_commit([](void* const Arg)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
*static_cast<bool* const>(Arg) = true;
|
|
|
|
|
}, &OuterTransaction);
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (OuterTransaction)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
autortfm_on_commit([](void* const Arg)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
*static_cast<bool* const>(Arg) = true;
|
|
|
|
|
}, &InnerTransaction);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (InnerTransaction)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NestResult = AutoRTFM::Transact([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
autortfm_on_commit([](void* const Arg)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
*static_cast<bool* const>(Arg) = true;
|
|
|
|
|
}, &InnerTransactionWithAbort);
|
|
|
|
|
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should never be modified because its transaction aborted!
|
|
|
|
|
if (InnerTransactionWithAbort)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
autortfm_on_commit([](void* const Arg)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
*static_cast<bool* const>(Arg) = true;
|
|
|
|
|
}, &InnerOpenNest);
|
|
|
|
|
|
|
|
|
|
// This should be modified immediately!
|
|
|
|
|
if (!InnerOpenNest)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == OuterTransaction);
|
|
|
|
|
REQUIRE(true == InnerTransaction);
|
|
|
|
|
REQUIRE(false == InnerTransactionWithAbort);
|
|
|
|
|
REQUIRE(true == InnerOpenNest);
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == NestResult);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 05:11:46 -05:00
|
|
|
TEST_CASE("API.autortfm_on_abort")
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
2024-06-03 05:47:03 -04:00
|
|
|
// Too hard to get this test working when retrying nested transactions so bail!
|
|
|
|
|
if (AutoRTFM::ForTheRuntime::ShouldRetryNestedTransactionsToo())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 23:06:47 -04:00
|
|
|
bool OuterTransaction = false;
|
|
|
|
|
bool InnerTransaction = false;
|
|
|
|
|
bool InnerTransactionWithAbort = false;
|
|
|
|
|
bool InnerOpenNest = false;
|
2024-06-03 05:47:03 -04:00
|
|
|
AutoRTFM::ETransactionResult NestResult = AutoRTFM::ETransactionResult::Committed;
|
2023-03-17 23:06:47 -04:00
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::Committed == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
2024-06-03 05:47:03 -04:00
|
|
|
// If we are retrying transactions, need to reset the test state.
|
|
|
|
|
AutoRTFM::OnAbort([&]
|
|
|
|
|
{
|
|
|
|
|
OuterTransaction = false;
|
|
|
|
|
InnerTransaction = false;
|
|
|
|
|
InnerTransactionWithAbort = false;
|
|
|
|
|
InnerOpenNest = false;
|
|
|
|
|
NestResult = AutoRTFM::ETransactionResult::Committed;
|
|
|
|
|
});
|
|
|
|
|
|
2024-01-09 05:11:46 -05:00
|
|
|
autortfm_on_abort([](void* const Arg)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
*static_cast<bool* const>(Arg) = true;
|
|
|
|
|
}, &OuterTransaction);
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (OuterTransaction)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
autortfm_on_abort([](void* const Arg)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
*static_cast<bool* const>(Arg) = true;
|
|
|
|
|
}, &InnerTransaction);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (InnerTransaction)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NestResult = AutoRTFM::Transact([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
autortfm_on_abort([](void* const Arg)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
*static_cast<bool* const>(Arg) = true;
|
|
|
|
|
}, &InnerTransactionWithAbort);
|
|
|
|
|
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
|
2024-05-16 17:41:22 -04:00
|
|
|
// OnAbort runs eagerly on inner abort
|
|
|
|
|
if (!InnerTransactionWithAbort)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
autortfm_on_abort([](void* const Arg)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
*static_cast<bool* const>(Arg) = true;
|
|
|
|
|
}, &InnerOpenNest);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (InnerOpenNest)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(false == OuterTransaction);
|
|
|
|
|
REQUIRE(false == InnerTransaction);
|
|
|
|
|
REQUIRE(true == InnerTransactionWithAbort);
|
|
|
|
|
REQUIRE(false == InnerOpenNest);
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == NestResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.autortfm_did_allocate")
|
|
|
|
|
{
|
|
|
|
|
constexpr unsigned Size = 1024;
|
|
|
|
|
unsigned BumpAllocator[Size];
|
|
|
|
|
unsigned NextBump = 0;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
2024-06-03 05:47:03 -04:00
|
|
|
// If we are retrying transactions, need to reset the test state.
|
|
|
|
|
AutoRTFM::OnAbort([&]
|
|
|
|
|
{
|
|
|
|
|
NextBump = 0;
|
|
|
|
|
});
|
|
|
|
|
|
2023-03-17 23:06:47 -04:00
|
|
|
for (unsigned I = 0; I < Size; I++)
|
|
|
|
|
{
|
|
|
|
|
unsigned* Data;
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
Data = reinterpret_cast<unsigned*>(autortfm_did_allocate(
|
|
|
|
|
&BumpAllocator[NextBump++],
|
|
|
|
|
sizeof(unsigned)));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
*Data = I;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (unsigned I = 0; I < Size; I++)
|
|
|
|
|
{
|
|
|
|
|
REQUIRE(I == BumpAllocator[I]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.autortfm_check_consistency_assuming_no_races")
|
|
|
|
|
{
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
autortfm_check_consistency_assuming_no_races();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.ETransactionResult")
|
|
|
|
|
{
|
|
|
|
|
int Answer = 6 * 9;
|
|
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::Committed == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
Answer = 42;
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(42 == Answer);
|
|
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
Answer = 13;
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(42 == Answer);
|
|
|
|
|
|
2023-05-11 05:22:24 -04:00
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == AutoRTFM::Transact([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
Answer = 13;
|
|
|
|
|
AutoRTFM::AbortIfTransactional();
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(42 == Answer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.IsTransactional")
|
|
|
|
|
{
|
|
|
|
|
REQUIRE(false == AutoRTFM::IsTransactional());
|
|
|
|
|
|
|
|
|
|
bool InTransaction = false;
|
|
|
|
|
bool InOpenNest = false;
|
2024-06-25 06:30:53 -04:00
|
|
|
bool InAbort = true;
|
|
|
|
|
bool InCommit = true;
|
2023-03-17 23:06:47 -04:00
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
InTransaction = AutoRTFM::IsTransactional();
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
InOpenNest = AutoRTFM::IsTransactional();
|
|
|
|
|
});
|
2024-06-25 06:30:53 -04:00
|
|
|
|
|
|
|
|
AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
AutoRTFM::OnAbort([&]
|
|
|
|
|
{
|
|
|
|
|
InAbort = AutoRTFM::IsTransactional();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AutoRTFM::AbortTransaction();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AutoRTFM::OnCommit([&]
|
|
|
|
|
{
|
|
|
|
|
InCommit = AutoRTFM::IsTransactional();
|
|
|
|
|
});
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == InTransaction);
|
|
|
|
|
REQUIRE(true == InOpenNest);
|
2024-06-25 06:30:53 -04:00
|
|
|
REQUIRE(false == InAbort);
|
|
|
|
|
REQUIRE(false == InCommit);
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.IsClosed")
|
|
|
|
|
{
|
|
|
|
|
REQUIRE(false == AutoRTFM::IsClosed());
|
|
|
|
|
|
|
|
|
|
// Set to the opposite of what we expect at the end of function.
|
|
|
|
|
bool InTransaction = false;
|
|
|
|
|
bool InOpenNest = true;
|
|
|
|
|
bool InClosedNestInOpenNest = false;
|
2024-06-25 06:30:53 -04:00
|
|
|
bool InAbort = true;
|
|
|
|
|
bool InCommit = true;
|
2023-03-17 23:06:47 -04:00
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
InTransaction = AutoRTFM::IsClosed();
|
|
|
|
|
|
2024-06-25 06:30:53 -04:00
|
|
|
AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
AutoRTFM::OnAbort([&]
|
|
|
|
|
{
|
|
|
|
|
InAbort = AutoRTFM::IsClosed();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AutoRTFM::AbortTransaction();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AutoRTFM::OnCommit([&]
|
|
|
|
|
{
|
|
|
|
|
InCommit = AutoRTFM::IsClosed();
|
|
|
|
|
});
|
|
|
|
|
|
2023-03-17 23:06:47 -04:00
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
InOpenNest = AutoRTFM::IsClosed();
|
|
|
|
|
|
2023-03-24 18:18:15 -04:00
|
|
|
REQUIRE(AutoRTFM::EContextStatus::OnTrack == AutoRTFM::Close([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InClosedNestInOpenNest = AutoRTFM::IsClosed();
|
2023-03-24 18:18:15 -04:00
|
|
|
}));
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == InTransaction);
|
|
|
|
|
REQUIRE(false == InOpenNest);
|
|
|
|
|
REQUIRE(true == InClosedNestInOpenNest);
|
2024-06-25 06:30:53 -04:00
|
|
|
REQUIRE(false == InAbort);
|
|
|
|
|
REQUIRE(false == InCommit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.IsCommittingOrAborting")
|
|
|
|
|
{
|
|
|
|
|
REQUIRE(false == AutoRTFM::IsCommittingOrAborting());
|
|
|
|
|
|
|
|
|
|
// Set to the opposite of what we expect at the end of function.
|
|
|
|
|
bool InTransaction = true;
|
|
|
|
|
bool InOpenNest = true;
|
|
|
|
|
bool InClosedNestInOpenNest = true;
|
|
|
|
|
bool InAbort = false;
|
|
|
|
|
bool InCommit = false;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
InTransaction = AutoRTFM::IsCommittingOrAborting();
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
AutoRTFM::OnAbort([&]
|
|
|
|
|
{
|
|
|
|
|
InAbort = AutoRTFM::IsCommittingOrAborting();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AutoRTFM::AbortTransaction();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AutoRTFM::OnCommit([&]
|
|
|
|
|
{
|
|
|
|
|
InCommit = AutoRTFM::IsCommittingOrAborting();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
InOpenNest = AutoRTFM::IsCommittingOrAborting();
|
|
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::EContextStatus::OnTrack == AutoRTFM::Close([&]
|
|
|
|
|
{
|
|
|
|
|
InClosedNestInOpenNest = AutoRTFM::IsCommittingOrAborting();
|
|
|
|
|
}));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(false == InTransaction);
|
|
|
|
|
REQUIRE(false == InOpenNest);
|
|
|
|
|
REQUIRE(false == InClosedNestInOpenNest);
|
|
|
|
|
REQUIRE(true == InAbort);
|
|
|
|
|
REQUIRE(true == InCommit);
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.Transact")
|
|
|
|
|
{
|
|
|
|
|
int Answer = 6 * 9;
|
|
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::Committed == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
Answer = 42;
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(42 == Answer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.Commit")
|
|
|
|
|
{
|
|
|
|
|
int Answer = 6 * 9;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
Answer = 42;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(42 == Answer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.Abort")
|
|
|
|
|
{
|
|
|
|
|
bool BeforeNest = false;
|
|
|
|
|
bool InNest = false;
|
|
|
|
|
bool AfterNest = false;
|
|
|
|
|
AutoRTFM::ETransactionResult NestResult;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
BeforeNest = true;
|
|
|
|
|
|
|
|
|
|
NestResult = AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
// Because we are aborting this won't actually occur!
|
|
|
|
|
InNest = true;
|
|
|
|
|
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AfterNest = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == BeforeNest);
|
|
|
|
|
REQUIRE(false == InNest);
|
|
|
|
|
REQUIRE(true == AfterNest);
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == NestResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.AbortIfTransactional")
|
|
|
|
|
{
|
|
|
|
|
// Calling this outwith any transaction won't abort the program.
|
|
|
|
|
AutoRTFM::AbortIfTransactional();
|
|
|
|
|
|
|
|
|
|
bool BeforeNest = false;
|
|
|
|
|
bool InNest = false;
|
|
|
|
|
bool AfterNest = false;
|
|
|
|
|
AutoRTFM::ETransactionResult NestResult;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
BeforeNest = true;
|
|
|
|
|
|
|
|
|
|
NestResult = AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
// Because we are aborting this won't actually occur!
|
|
|
|
|
InNest = true;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::AbortIfTransactional();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AfterNest = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == BeforeNest);
|
|
|
|
|
REQUIRE(false == InNest);
|
|
|
|
|
REQUIRE(true == AfterNest);
|
2023-05-11 05:22:24 -04:00
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == NestResult);
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.AbortIfClosed")
|
|
|
|
|
{
|
|
|
|
|
// Calling this outwith any transaction won't abort the program.
|
|
|
|
|
AutoRTFM::AbortIfClosed();
|
|
|
|
|
|
|
|
|
|
bool BeforeNest = false;
|
|
|
|
|
bool InNest = false;
|
|
|
|
|
bool AfterNest = false;
|
|
|
|
|
|
2023-05-11 05:22:24 -04:00
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == AutoRTFM::Transact([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
BeforeNest = true;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
InNest = true;
|
|
|
|
|
|
|
|
|
|
// This won't abort because we aren't closed!
|
|
|
|
|
AutoRTFM::AbortIfClosed();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
AfterNest = true;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::AbortIfClosed();
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(false == BeforeNest);
|
|
|
|
|
REQUIRE(true == InNest);
|
|
|
|
|
REQUIRE(false == AfterNest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.Open")
|
|
|
|
|
{
|
|
|
|
|
int Answer = 6 * 9;
|
|
|
|
|
|
|
|
|
|
// An open call outside a transaction succeeds.
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
Answer = 42;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(42 == Answer);
|
|
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
// An open call inside a transaction succeeds also.
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
Answer *= 2;
|
|
|
|
|
});
|
|
|
|
|
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(84 == Answer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.Close")
|
|
|
|
|
{
|
|
|
|
|
bool InClosedNest = false;
|
|
|
|
|
bool InOpenNest = false;
|
|
|
|
|
bool InClosedNestInOpenNest = false;
|
|
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
|
|
|
|
// A closed call inside a transaction does not abort.
|
2023-03-24 18:18:15 -04:00
|
|
|
REQUIRE(AutoRTFM::EContextStatus::OnTrack == AutoRTFM::Close([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InClosedNest = true;
|
2023-03-24 18:18:15 -04:00
|
|
|
}));
|
2023-03-17 23:06:47 -04:00
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
// A closed call inside an open does not abort either.
|
2023-03-24 12:04:10 -04:00
|
|
|
REQUIRE(AutoRTFM::EContextStatus::OnTrack == AutoRTFM::Close([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InClosedNestInOpenNest = true;
|
2023-03-24 12:04:10 -04:00
|
|
|
}));
|
2023-03-17 23:06:47 -04:00
|
|
|
|
|
|
|
|
InOpenNest = true;
|
|
|
|
|
});
|
|
|
|
|
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(false == InClosedNest);
|
|
|
|
|
REQUIRE(true == InOpenNest);
|
|
|
|
|
REQUIRE(false == InClosedNestInOpenNest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.RegisterOpenFunction")
|
|
|
|
|
{
|
2024-01-17 05:59:25 -05:00
|
|
|
AutoRTFM::ForTheRuntime::RegisterOpenFunction(
|
2023-03-17 23:06:47 -04:00
|
|
|
reinterpret_cast<void*>(NoAutoRTFM::DoSomethingCpp),
|
|
|
|
|
reinterpret_cast<void*>(NoAutoRTFM::DoSomethingInTransactionCpp));
|
|
|
|
|
|
|
|
|
|
int I = -42;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
I = NoAutoRTFM::DoSomethingCpp(I);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
REQUIRE(0 == I);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 05:11:46 -05:00
|
|
|
TEST_CASE("API.OnCommit")
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
bool OuterTransaction = false;
|
|
|
|
|
bool InnerTransaction = false;
|
|
|
|
|
bool InnerTransactionWithAbort = false;
|
|
|
|
|
bool InnerOpenNest = false;
|
|
|
|
|
AutoRTFM::ETransactionResult NestResult;
|
|
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::Committed == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
AutoRTFM::OnCommit([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
OuterTransaction = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (OuterTransaction)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
AutoRTFM::OnCommit([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InnerTransaction = true;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (InnerTransaction)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NestResult = AutoRTFM::Transact([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
AutoRTFM::OnCommit([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InnerTransactionWithAbort = true;
|
|
|
|
|
});
|
|
|
|
|
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should never be modified because its transaction aborted!
|
|
|
|
|
if (InnerTransactionWithAbort)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
AutoRTFM::OnCommit([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InnerOpenNest = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should be modified immediately!
|
|
|
|
|
if (!InnerOpenNest)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(true == OuterTransaction);
|
|
|
|
|
REQUIRE(true == InnerTransaction);
|
|
|
|
|
REQUIRE(false == InnerTransactionWithAbort);
|
|
|
|
|
REQUIRE(true == InnerOpenNest);
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == NestResult);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 05:11:46 -05:00
|
|
|
TEST_CASE("API.OnAbort")
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
2024-06-03 05:47:03 -04:00
|
|
|
// Too hard to get this test working when retrying nested transactions so bail!
|
|
|
|
|
if (AutoRTFM::ForTheRuntime::ShouldRetryNestedTransactionsToo())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 23:06:47 -04:00
|
|
|
bool OuterTransaction = false;
|
|
|
|
|
bool InnerTransaction = false;
|
|
|
|
|
bool InnerTransactionWithAbort = false;
|
|
|
|
|
bool InnerOpenNest = false;
|
2024-06-03 05:47:03 -04:00
|
|
|
AutoRTFM::ETransactionResult NestResult = AutoRTFM::ETransactionResult::Committed;
|
2023-03-17 23:06:47 -04:00
|
|
|
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::Committed == AutoRTFM::Transact([&]
|
|
|
|
|
{
|
2024-06-03 05:47:03 -04:00
|
|
|
// If we are retrying transactions, need to reset the test state.
|
|
|
|
|
AutoRTFM::OnAbort([&]
|
|
|
|
|
{
|
|
|
|
|
OuterTransaction = false;
|
|
|
|
|
InnerTransaction = false;
|
|
|
|
|
InnerTransactionWithAbort = false;
|
|
|
|
|
InnerOpenNest = false;
|
|
|
|
|
NestResult = AutoRTFM::ETransactionResult::Committed;
|
|
|
|
|
});
|
|
|
|
|
|
2024-01-09 05:11:46 -05:00
|
|
|
AutoRTFM::OnAbort([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
OuterTransaction = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (OuterTransaction)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
AutoRTFM::OnAbort([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InnerTransaction = true;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (InnerTransaction)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NestResult = AutoRTFM::Transact([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
AutoRTFM::OnAbort([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InnerTransactionWithAbort = true;
|
|
|
|
|
});
|
|
|
|
|
|
2024-05-16 17:41:22 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
|
2024-05-16 17:41:22 -04:00
|
|
|
// Inner OnAbort runs eagerly
|
|
|
|
|
if (!InnerTransactionWithAbort)
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
2024-01-09 05:11:46 -05:00
|
|
|
AutoRTFM::OnAbort([&]
|
2023-03-17 23:06:47 -04:00
|
|
|
{
|
|
|
|
|
InnerOpenNest = true;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// This should only be modified on the commit!
|
|
|
|
|
if (InnerOpenNest)
|
|
|
|
|
{
|
2023-03-22 19:46:30 -04:00
|
|
|
AutoRTFM::AbortTransaction();
|
2023-03-17 23:06:47 -04:00
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
REQUIRE(false == OuterTransaction);
|
|
|
|
|
REQUIRE(false == InnerTransaction);
|
|
|
|
|
REQUIRE(true == InnerTransactionWithAbort);
|
|
|
|
|
REQUIRE(false == InnerOpenNest);
|
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == NestResult);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.DidAllocate")
|
|
|
|
|
{
|
|
|
|
|
constexpr unsigned Size = 1024;
|
|
|
|
|
unsigned BumpAllocator[Size];
|
|
|
|
|
unsigned NextBump = 0;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
2024-06-03 05:47:03 -04:00
|
|
|
// If we are retrying transactions, need to reset the test state.
|
|
|
|
|
AutoRTFM::OnAbort([&]
|
|
|
|
|
{
|
|
|
|
|
NextBump = 0;
|
|
|
|
|
});
|
|
|
|
|
|
2023-03-17 23:06:47 -04:00
|
|
|
for (unsigned I = 0; I < Size; I++)
|
|
|
|
|
{
|
|
|
|
|
unsigned* Data;
|
|
|
|
|
AutoRTFM::Open([&]
|
|
|
|
|
{
|
|
|
|
|
Data = reinterpret_cast<unsigned*>(AutoRTFM::DidAllocate(
|
|
|
|
|
&BumpAllocator[NextBump++],
|
|
|
|
|
sizeof(unsigned)));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
*Data = I;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (unsigned I = 0; I < Size; I++)
|
|
|
|
|
{
|
|
|
|
|
REQUIRE(I == BumpAllocator[I]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("API.CheckConsistencyAssumingNoRaces")
|
|
|
|
|
{
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
2024-01-17 05:59:25 -05:00
|
|
|
AutoRTFM::ForTheRuntime::CheckConsistencyAssumingNoRaces();
|
2023-03-17 23:06:47 -04:00
|
|
|
});
|
|
|
|
|
}
|
2024-08-30 15:31:51 -04:00
|
|
|
|
2024-09-04 09:09:31 -04:00
|
|
|
TEST_CASE("API.IsOnCurrentTransactionStack")
|
2024-08-30 15:31:51 -04:00
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
int OnStackNotInTransaction = 1;
|
2024-09-04 09:09:31 -04:00
|
|
|
REQUIRE(!AutoRTFM::IsOnCurrentTransactionStack(&OnStackNotInTransaction));
|
2024-08-30 15:31:51 -04:00
|
|
|
|
|
|
|
|
int* OnHeapNotInTransaction = new int{2};
|
2024-09-04 09:09:31 -04:00
|
|
|
REQUIRE(!AutoRTFM::IsOnCurrentTransactionStack(OnHeapNotInTransaction));
|
2024-08-30 15:31:51 -04:00
|
|
|
delete OnHeapNotInTransaction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
int OnStackInTransaction = 3;
|
2024-09-04 09:09:31 -04:00
|
|
|
REQUIRE(AutoRTFM::IsOnCurrentTransactionStack(&OnStackInTransaction));
|
2024-08-30 15:31:51 -04:00
|
|
|
|
|
|
|
|
int* OnHeapInTransaction = new int{4};
|
2024-09-04 09:09:31 -04:00
|
|
|
REQUIRE(!AutoRTFM::IsOnCurrentTransactionStack(OnHeapInTransaction));
|
2024-08-30 15:31:51 -04:00
|
|
|
delete OnHeapInTransaction;
|
|
|
|
|
|
|
|
|
|
AutoRTFM::Commit([&]
|
|
|
|
|
{
|
|
|
|
|
// `OnStackInTransaction` is no longer in the innermost scope.
|
2024-09-04 09:09:31 -04:00
|
|
|
REQUIRE(!AutoRTFM::IsOnCurrentTransactionStack(&OnStackInTransaction));
|
2024-08-30 15:31:51 -04:00
|
|
|
|
|
|
|
|
int OnInnermostStackInTransaction = 5;
|
2024-09-04 09:09:31 -04:00
|
|
|
REQUIRE(AutoRTFM::IsOnCurrentTransactionStack(&OnInnermostStackInTransaction));
|
2024-08-30 15:31:51 -04:00
|
|
|
});
|
|
|
|
|
});
|
2024-09-04 09:09:31 -04:00
|
|
|
}
|