Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,46 @@ jobs:
- name: Install g++
if: startsWith(matrix.compiler.cxx, 'g++') && (matrix.compiler.ver == 13 || matrix.compiler.ver == 9)
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get install g++-${{ matrix.compiler.ver }}
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${{ matrix.compiler.ver }} ${{ matrix.compiler.ver }}
requested="g++-${{ matrix.compiler.ver }}"

if command -v g++-${{ matrix.compiler.ver }} >/dev/null 2>&1; then
echo "g++-${{ matrix.compiler.ver }} is already available on the runner"
else
retry() {
local attempts="$1"
shift
local try=1
while true; do
"$@" && break
if [ "$try" -ge "$attempts" ]; then
return 1
fi
echo "Command failed, retrying ($try/$attempts): $*"
try=$((try + 1))
sleep 10
done
}

if retry 3 sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test && \
retry 3 sudo apt-get update && \
retry 3 sudo apt-get install -y "$requested"; then
echo "Installed $requested from PPA"
else
echo "::warning::Failed to install $requested from Launchpad PPA (network timeout). Falling back to system g++."
if ! command -v g++ >/dev/null 2>&1; then
echo "::error::Neither $requested nor system g++ is available."
exit 1
fi
fallback_cxx="$(command -v g++)"
echo "CXX=$fallback_cxx" >> "$GITHUB_ENV"
echo "Using fallback compiler: $fallback_cxx"
exit 0
fi
fi

if command -v "$requested" >/dev/null 2>&1; then
sudo update-alternatives --install /usr/bin/g++ g++ "$(command -v "$requested")" ${{ matrix.compiler.ver }}
fi

- name: Install Clang
if: startsWith(matrix.compiler.cxx, 'clang') && matrix.compiler.ver < 13
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ install
trace.json
.cache/
build_examples/
.kiro
37 changes: 23 additions & 14 deletions orm_lib/tests/db_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2741,11 +2741,9 @@ DROGON_TEST(MySQLTest)
#endif

#if USE_SQLITE3
DbClientPtr sqlite3Client;

DROGON_TEST(SQLite3Test)
{
auto &clientPtr = sqlite3Client;
auto clientPtr = DbClient::newSqlite3Client("filename=:memory:", 1);
REQUIRE(clientPtr != nullptr);

// Prepare the test environment
Expand Down Expand Up @@ -4066,7 +4064,7 @@ DROGON_TEST(SQLite3Test)
#if USE_SQLITE3
DROGON_TEST(SQLite3TransactionTypeTest)
{
auto &clientPtr = sqlite3Client;
auto clientPtr = DbClient::newSqlite3Client("filename=:memory:", 1);
REQUIRE(clientPtr != nullptr);

// Ensure the test table exists
Expand Down Expand Up @@ -4179,7 +4177,10 @@ DROGON_TEST(SQLite3TransactionTypeLockingTest)
{
// A pool of 2 connections to a shared file-based database gives us two
// independent SQLite connections that observe each other's locks.
const std::string dbPath = "/tmp/drogon_trans_type_lock_test.db";
const auto nonce =
std::chrono::steady_clock::now().time_since_epoch().count();
const auto dbPath =
"drogon_trans_type_lock_test_" + std::to_string(nonce) + ".db";
std::remove(dbPath.c_str());

auto pool = DbClient::newSqlite3Client("filename=" + dbPath, 2);
Expand All @@ -4194,13 +4195,24 @@ DROGON_TEST(SQLite3TransactionTypeLockingTest)
pool->execSqlSync(
"CREATE TABLE IF NOT EXISTS lock_test (id INTEGER PRIMARY KEY)");

std::shared_ptr<Transaction> transA;
// Hold an IMMEDIATE transaction on connection A.
auto transA = pool->newTransaction(TransactionType::Immediate);
// doBegin() is asynchronous — the BEGIN IMMEDIATE is queued to the
// connection's event loop. Run a synchronous query through the transaction
// to flush the queue; once execSqlSync returns, the RESERVED lock is
// definitely held.
transA->execSqlSync("SELECT 1");
try
{
transA = pool->newTransaction(TransactionType::Immediate);
// doBegin() is asynchronous — the BEGIN IMMEDIATE is queued to the
// connection's event loop. Run a synchronous query through the
// transaction to flush the queue; once execSqlSync returns, the
// RESERVED lock is definitely held.
transA->execSqlSync("SELECT 1");
}
catch (const DrogonDbException &e)
{
std::remove(dbPath.c_str());
FAULT("sqlite3 - TransactionType::Immediate locking setup what():",
e.base().what());
return;
}

// Connection B attempting BEGIN IMMEDIATE must fail because A already
// holds the RESERVED lock. SQLite's default busy_timeout is 0.
Expand Down Expand Up @@ -4249,9 +4261,6 @@ int main(int argc, char **argv)
"client_encoding=utf8",
1,
true);
#endif
#if USE_SQLITE3
sqlite3Client = DbClient::newSqlite3Client("filename=:memory:", 1);
#endif
const int testStatus = test::run(argc, argv);
return testStatus;
Expand Down
Loading