sourcemod/plugins/testsuite/sqltest.sp
David Anderson 63ad5eff18 Introduce basic methodmaps (PR #38).
commit 1e5213d43fdd170bb0c30af914a4e40610014b2b
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 04:09:27 2014 -0700

    Quell MSVC C99 bugs.

commit f2e166c5925fda49b5abeadc0aa0f9156b99cf11
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 03:59:23 2014 -0700

    Fix varying levels of stupid memory errors.

commit b0773d7be45345351ab1c1738681d5215a97f3f3
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 03:36:39 2014 -0700

    Fix memory leak in parsing some control flow structures.

commit 5aca55713cfc2dd09c5900132fc4a6be51e3e309
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 03:35:17 2014 -0700

    Fix memory leak in struct parsing.

commit b46ec5cd281b46177e83c4f0a4acac9cc1065c53
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 03:32:03 2014 -0700

    Fix build.

commit 17bbbb9a46bfc00862adca7d3e15369a48e9ac0f
Merge: c083409 2107599
Author: David Anderson <dvander@alliedmods.net>
Date:   Sat Jun 21 01:26:27 2014 -0700

    Merge branch 'master' into methodmaps

commit c083409b569abff13f24d3b8c47f8ff199036840
Author: David Anderson <dvander@alliedmods.net>
Date:   Fri Jun 20 23:49:36 2014 -0700

    Add VS2k13 support.

commit b7993778494d538cb1c1965116030142a7f7765b
Author: David Anderson <dvander@alliedmods.net>
Date:   Fri Jun 20 01:28:08 2014 -0700

    Implement destructors.

commit 1a340dec260d079ed1b79351ed7b50b58a997cea
Author: David Anderson <dvander@alliedmods.net>
Date:   Fri Jun 20 00:08:04 2014 -0700

    Add some tests.

commit 12db52ee64eb009ead9294495e9034c63ab75b09
Author: David Anderson <dvander@alliedmods.net>
Date:   Fri Jun 20 00:05:49 2014 -0700

    Initial implementation of constructors.

commit 074669a658caa2822aa864164b615a244c00a0bc
Author: David Anderson <dvander@alliedmods.net>
Date:   Thu Jun 19 22:42:35 2014 -0700

    Add simple test harness.

commit 27c1e3cf14e1e6c5cf35c80c792cce2744b804d7
Author: David Anderson <dvander@alliedmods.net>
Date:   Thu Jun 19 22:15:42 2014 -0700

    Big refactoring for new syntax.

commit f3c37fdc919e76ee0815e2394cbe8d221f9fc0ca
Author: David Anderson <dvander@alliedmods.net>
Date:   Thu Jun 19 22:12:54 2014 -0700

    Refactor tests for the new syntax.

commit 6211f392f8e722b907474cf380cfac4347e46b8e
Author: David Anderson <dvander@alliedmods.net>
Date:   Wed Jun 18 22:25:48 2014 -0700

    Make lexer tokens an enum.

commit 5210b013756b0b00de3a61c6490685c768ff8cbd
Author: David Anderson <dvander@alliedmods.net>
Date:   Tue Jun 17 06:48:15 2014 -0700

    Add comment.

commit 06688ff4aced14077dd21a9cc1db4c26c7420ff3
Author: David Anderson <dvander@alliedmods.net>
Date:   Tue Jun 17 06:46:10 2014 -0700

    Allow |this| to be a base type of the methodmap.

commit 05cf3682020e0e6d9f47b1a0a6727b9edbfe7622
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 22:11:58 2014 -0700

    Unify duplicate typesymbol checking.

commit 09161bf2691c8c1ed25b9b70fda01c336f21aa0b
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 19:53:36 2014 -0700

    Close loophole that allowed methodmaps for enums.

commit 5bb4aeba89fec47a4de7a7532d27830999d1fcb4
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:50:42 2014 -0700

    Add tests and dbi/handle changes.

commit b9203e2491daec2a8073874d6375949483778d14
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:38:29 2014 -0700

    Ensure methodmap tags are fixed.

commit 878b80fd87a2ea500d3a28ce2d53f616d1efe5e8
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:36:04 2014 -0700

    Implement inheritance.

commit 6ba9e004fbae18ad68056368ddd0affdc78659f1
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:31:00 2014 -0700

    Refactor matchtag() to not be insane.

commit 4ede6343b0682c6df98fa869153828e92f891bcc
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:20:50 2014 -0700

    Fix indenting.

commit e3ddef8916e3dd5f4ff0fe571d6e1c3acd163352
Author: David Anderson <dvander@alliedmods.net>
Date:   Mon Jun 16 01:20:27 2014 -0700

    Initial prototype.
2014-06-21 04:10:15 -07:00

319 lines
8.7 KiB
SourcePawn

#include <sourcemod>
#include <testing>
public Plugin:myinfo =
{
name = "SQL Testing Lab",
author = "AlliedModders LLC",
description = "Tests basic function calls",
version = "1.0.0.0",
url = "http://www.sourcemod.net/"
};
public OnPluginStart()
{
RegServerCmd("sql_test_normal", Command_TestSql1)
RegServerCmd("sql_test_stmt", Command_TestSql2)
RegServerCmd("sql_test_thread1", Command_TestSql3)
RegServerCmd("sql_test_thread2", Command_TestSql4)
RegServerCmd("sql_test_thread3", Command_TestSql5)
RegServerCmd("sql_test_txn", Command_TestTxn)
new Handle:hibernate = FindConVar("sv_hibernate_when_empty");
if (hibernate != INVALID_HANDLE) {
ServerCommand("sv_hibernate_when_empty 0");
}
}
PrintQueryData(Handle:query)
{
if (!SQL_HasResultSet(query))
{
PrintToServer("Query Handle %x has no results", query)
return
}
new rows = SQL_GetRowCount(query)
new fields = SQL_GetFieldCount(query)
decl String:fieldNames[fields][32]
PrintToServer("Fields: %d", fields)
for (new i=0; i<fields; i++)
{
SQL_FieldNumToName(query, i, fieldNames[i], 32)
PrintToServer("-> Field %d: \"%s\"", i, fieldNames[i])
}
PrintToServer("Rows: %d", rows)
decl String:result[255]
new row
while (SQL_FetchRow(query))
{
row++
PrintToServer("Row %d:", row)
for (new i=0; i<fields; i++)
{
SQL_FetchString(query, i, result, sizeof(result))
PrintToServer(" [%s] %s", fieldNames[i], result)
}
}
}
public Action:Command_TestSql1(args)
{
new String:error[255]
new Handle:db = SQL_DefConnect(error, sizeof(error))
if (db == INVALID_HANDLE)
{
PrintToServer("Failed to connect: %s", error)
return Plugin_Handled
}
new Handle:query = SQL_Query(db, "SELECT * FROM gab")
if (query == INVALID_HANDLE)
{
SQL_GetError(db, error, sizeof(error))
PrintToServer("Failed to query: %s", error)
} else {
PrintQueryData(query)
CloseHandle(query)
}
CloseHandle(db)
return Plugin_Handled;
}
public Action:Command_TestSql2(args)
{
new String:error[255]
new Handle:db = SQL_DefConnect(error, sizeof(error))
if (db == INVALID_HANDLE)
{
PrintToServer("Failed to connect: %s", error)
return Plugin_Handled
}
new Handle:stmt = SQL_PrepareQuery(db, "SELECT * FROM gab WHERE gaben > ?", error, sizeof(error))
if (stmt == INVALID_HANDLE)
{
PrintToServer("Failed to prepare query: %s", error)
} else {
SQL_BindParamInt(stmt, 0, 1)
if (!SQL_Execute(stmt))
{
SQL_GetError(stmt, error, sizeof(error))
PrintToServer("Failed to execute query: %s", error)
} else {
PrintQueryData(stmt)
}
CloseHandle(stmt)
}
CloseHandle(db)
return Plugin_Handled;
}
new Handle:g_ThreadedHandle = INVALID_HANDLE;
public CallbackTest3(Handle:owner, Handle:hndl, const String:error[], any:data)
{
PrintToServer("CallbackTest1() (owner %x) (hndl %x) (error \"%s\") (data %d)", owner, hndl, error, data);
if (g_ThreadedHandle != INVALID_HANDLE && hndl != INVALID_HANDLE)
{
CloseHandle(hndl);
} else {
g_ThreadedHandle = hndl;
}
}
public Action:Command_TestSql3(args)
{
if (g_ThreadedHandle != INVALID_HANDLE)
{
PrintToServer("A threaded connection already exists, run the next test");
return Plugin_Handled;
}
new String:name[32];
GetCmdArg(1, name, sizeof(name));
SQL_TConnect(CallbackTest3, name);
return Plugin_Handled;
}
public Action:Command_TestSql4(args)
{
SQL_LockDatabase(g_ThreadedHandle);
new Handle:query = SQL_Query(g_ThreadedHandle, "SELECT * FROM gab")
if (query == INVALID_HANDLE)
{
new String:error[255];
SQL_GetError(g_ThreadedHandle, error, sizeof(error))
PrintToServer("Failed to query: %s", error)
} else {
PrintQueryData(query)
CloseHandle(query)
}
SQL_UnlockDatabase(g_ThreadedHandle);
return Plugin_Handled;
}
public CallbackTest5(Handle:owner, Handle:hndl, const String:error[], any:data)
{
if (hndl == INVALID_HANDLE)
{
PrintToServer("Failed to query: %s", error)
} else {
PrintQueryData(hndl)
SQL_TQuery(g_ThreadedHandle, CallbackTest6, "UPDATE gab SET `gaben` = `gaben` + 1 WHERE `gaben` >= 4", 52)
}
}
public CallbackTest6(Handle:owner, Handle:hndl, const String:error[], any:data)
{
if (hndl == INVALID_HANDLE)
{
PrintToServer("Failed to query: %s", error)
} else {
PrintToServer("Queried!");
SQL_TQuery(g_ThreadedHandle, CallbackTest7, "UPDATE gab SET `gaben` = `gaben` + 1 WHERE `gaben` >= 4", 52)
}
}
public CallbackTest7(Handle:owner, Handle:hndl, const String:error[], any:data)
{
if (hndl == INVALID_HANDLE)
{
PrintToServer("Failed to query: %s", error)
} else {
PrintToServer("Queried!");
}
}
public Action:Command_TestSql5(args)
{
SQL_TQuery(g_ThreadedHandle, CallbackTest5, "SELECT * FROM gab", 52)
SQL_TQuery(g_ThreadedHandle, CallbackTest5, "SELECT * FROM gab", 52)
SQL_TQuery(g_ThreadedHandle, CallbackTest5, "SELECT * FROM gab", 52)
SQL_TQuery(g_ThreadedHandle, CallbackTest5, "SELECT * FROM gab", 52)
return Plugin_Handled;
}
FastQuery(Handle:db, const String:query[])
{
new String:error[256];
if (!SQL_FastQuery(db, query)) {
SQL_GetError(db, error, sizeof(error));
ThrowError("ERROR: %s", error);
}
}
public Txn_Test1_OnSuccess(Handle:db, any:data, numQueries, Handle:results[], any:queryData[])
{
SetTestContext("Transaction Test 1");
AssertEq("data", data, 1000);
AssertEq("numQueries", numQueries, 3);
AssertEq("queryData[0]", queryData[0], 50);
AssertEq("queryData[1]", queryData[1], 60);
AssertEq("queryData[2]", queryData[2], 70);
AssertFalse("HasResultSet(0)", SQL_HasResultSet(results[0]));
AssertFalse("HasResultSet(1)", SQL_HasResultSet(results[1]));
AssertTrue("HasResultSet(2)", SQL_HasResultSet(results[2]));
AssertTrue("FetchRow(2)", SQL_FetchRow(results[2]));
AssertEq("FetchInt(2, 0)", SQL_FetchInt(results[2], 0), 5);
AssertFalse("FetchRow(2)", SQL_FetchRow(results[2]));
}
public Txn_Test1_OnFailure(Handle:db, any:data, numQueries, const String:error[], failIndex, any:queryData[])
{
ThrowError("Transaction test 1 failed: %s (failIndex=%d)", error, failIndex);
}
public Txn_Test2_OnSuccess(Handle:db, any:data, numQueries, Handle:results[], any:queryData[])
{
ThrowError("Transaction test 2 failed: should have failed");
}
public Txn_Test2_OnFailure(Handle:db, any:data, numQueries, const String:error[], failIndex, any:queryData[])
{
SetTestContext("Transaction Test 2");
AssertEq("data", data, 1000);
AssertEq("numQueries", numQueries, 3);
AssertEq("queryData[0]", queryData[0], 50);
AssertEq("queryData[1]", queryData[1], 60);
AssertEq("queryData[2]", queryData[2], 70);
AssertEq("failIndex", failIndex, 1);
}
public Txn_Test3_OnSuccess(Handle:db, any:data, numQueries, Handle:results[], any:queryData[])
{
SetTestContext("Transaction Test 3");
AssertEq("data", data, 0);
AssertEq("numQueries", numQueries, 1);
AssertEq("queryData[0]", queryData[0], 0);
AssertTrue("HasResultSet(0)", SQL_HasResultSet(results[0]));
AssertTrue("FetchRow(0)", SQL_FetchRow(results[0]));
AssertEq("FetchInt(0, 0)", SQL_FetchInt(results[0], 0), 5);
}
public Action:Command_TestTxn(args)
{
new String:error[256];
new Handle:db = SQL_Connect("storage-local", false, error, sizeof(error));
if (db == INVALID_HANDLE) {
ThrowError("ERROR: %s", error);
return Plugin_Handled;
}
FastQuery(db, "DROP TABLE IF EXISTS egg");
FastQuery(db, "CREATE TABLE egg(id int primary key)");
FastQuery(db, "INSERT INTO egg (id) VALUES (1)");
FastQuery(db, "INSERT INTO egg (id) VALUES (2)");
FastQuery(db, "INSERT INTO egg (id) VALUES (3)");
SetTestContext("CreateTransaction");
new Transaction:txn = SQL_CreateTransaction();
AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (4)", 50), 0);
AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (5)", 60), 1);
AssertEq("AddQuery", txn.AddQuery("SELECT COUNT(id) FROM egg", 70), 2);
SQL_ExecuteTransaction(
db,
txn,
Txn_Test1_OnSuccess,
Txn_Test1_OnFailure,
1000
);
txn = SQL_CreateTransaction();
AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (6)", 50), 0);
AssertEq("AddQuery", txn.AddQuery("INSERT INTO egg (id) VALUES (6)", 60), 1);
AssertEq("AddQuery", txn.AddQuery("SELECT COUNT(id) FROM egg", 70), 2);
SQL_ExecuteTransaction(
db,
txn,
Txn_Test2_OnSuccess,
Txn_Test2_OnFailure,
1000
);
// Make sure the transaction was rolled back - COUNT should be 5.
txn = SQL_CreateTransaction();
AssertEq("CloneHandle", _:CloneHandle(txn), _:INVALID_HANDLE);
txn.AddQuery("SELECT COUNT(id) FROM egg");
SQL_ExecuteTransaction(
db,
txn,
Txn_Test3_OnSuccess
);
db.Close();
return Plugin_Handled;
}