250 lines
9.8 KiB
Plaintext
250 lines
9.8 KiB
Plaintext
#include "nwnx_sql"
|
|
#include "nwnx_object"
|
|
#include "nwnx_tests"
|
|
|
|
void cleanup()
|
|
{
|
|
NWNX_Tests_Report("NWNX_SQL", "Cleanup sql_test", NWNX_SQL_ExecuteQuery("DROP TABLE sql_test"));
|
|
NWNX_Tests_Report("NWNX_SQL", "Cleanup stress_test", NWNX_SQL_ExecuteQuery("DROP TABLE stress_test"));
|
|
NWNX_Tests_Report("NWNX_SQL", "Cleanup error_test", NWNX_SQL_ExecuteQuery("DROP TABLE error_test"));
|
|
}
|
|
|
|
void main()
|
|
{
|
|
WriteTimestampedLogEntry("NWNX_SQL unit test begin..");
|
|
|
|
string db_type = GetStringUpperCase(NWNX_SQL_GetDatabaseType());
|
|
WriteTimestampedLogEntry("Testing database " + db_type);
|
|
|
|
string sCreate = "";
|
|
string sInsert = "";
|
|
|
|
/* MySQL and SQLite version */
|
|
if (db_type == "MYSQL" || db_type == "SQLITE")
|
|
{
|
|
sCreate = "CREATE TABLE sql_test (" +
|
|
"colInt INT, colFloat FLOAT, colStr VARCHAR(256)," +
|
|
"colObjId INT, colObj TEXT(1000000) );";
|
|
|
|
sInsert = "INSERT INTO sql_test(colInt, colFloat, colStr, colObjId, colObj) VALUES(?, ?, ?, ?, ?)";
|
|
}
|
|
|
|
/* PostgreSQL version */
|
|
if (db_type == "POSTGRESQL")
|
|
{
|
|
sCreate = "CREATE TABLE sql_test (" +
|
|
"colInt INT, colFloat FLOAT, colStr VARCHAR(256)," +
|
|
"colObjId INT, colObj TEXT );";
|
|
|
|
// Even though we're using 0 based parameter numbers, PostgreSQL requires the parameter
|
|
// numbers in the actual SQL string to be 1 based (e.g. $1, $2... not $0, $1... )
|
|
sInsert = "INSERT INTO sql_test(colInt, colFloat, colStr, colObjId, colObj) VALUES($1, $2, $3, $4, $5)";
|
|
}
|
|
|
|
int b = NWNX_SQL_ExecuteQuery(sCreate);
|
|
NWNX_Tests_Report("NWNX_SQL", "Create Table", b);
|
|
|
|
object o = CreateObject(OBJECT_TYPE_CREATURE, "nw_chicken", GetStartingLocation());
|
|
if (!GetIsObjectValid(o))
|
|
{
|
|
WriteTimestampedLogEntry("NWNX_SQL test: Failed to create creature");
|
|
cleanup();
|
|
return;
|
|
}
|
|
|
|
vector v = Vector(5.0, 5.0, 0.0); // slightly different location.
|
|
|
|
b = NWNX_SQL_PrepareQuery(sInsert);
|
|
NWNX_Tests_Report("NWNX_SQL", "Complex PrepareQuery", b);
|
|
NWNX_Tests_Report("NWNX_SQL", "GetPreparedQueryParamCount", NWNX_SQL_GetPreparedQueryParamCount() == 5);
|
|
|
|
NWNX_SQL_PreparedInt(0, 42);
|
|
NWNX_SQL_PreparedFloat(1, 0.42);
|
|
NWNX_SQL_PreparedString(2, "FourtyTwooo");
|
|
NWNX_SQL_PreparedObjectId(3, o);
|
|
NWNX_SQL_PreparedObjectFull(4, o);
|
|
|
|
b = NWNX_SQL_ExecutePreparedQuery();
|
|
NWNX_Tests_Report("NWNX_SQL", "Complex ExecutePreparedQuery", b);
|
|
|
|
b = NWNX_SQL_ExecuteQuery("SELECT * FROM sql_test;");
|
|
NWNX_Tests_Report("NWNX_SQL", "Select ExecuteQuery", b);
|
|
|
|
if (b)
|
|
{
|
|
while (NWNX_SQL_ReadyToReadNextRow())
|
|
{
|
|
NWNX_SQL_ReadNextRow();
|
|
int n = StringToInt(NWNX_SQL_ReadDataInActiveRow(0));
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadInt", n == 42);
|
|
float f = StringToFloat(NWNX_SQL_ReadDataInActiveRow(1));
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadFloat", fabs(f - 0.42) < 0.01);
|
|
string s = NWNX_SQL_ReadDataInActiveRow(2);
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadString", s == "FourtyTwooo");
|
|
|
|
string sObjId = NWNX_SQL_ReadDataInActiveRow(3); // In base 10
|
|
object o2 = NWNX_Object_StringToObject(IntToHexString(StringToInt(sObjId)));
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadObjectId", o == o2);
|
|
|
|
object o3 = NWNX_SQL_ReadFullObjectInActiveRow(4, GetArea(o), v.x, v.y, v.z);
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadFullObject", GetIsObjectValid(o3));
|
|
// Alternatively:
|
|
// object o3 = NWNX_Object_Deserialize(NWNX_SQL_ReadDataInActiveRow(4));
|
|
}
|
|
}
|
|
|
|
|
|
object oPlc = CreateObject(OBJECT_TYPE_PLACEABLE, "nw_plc_chestburd", GetStartingLocation());
|
|
object oItem = CreateObject(OBJECT_TYPE_ITEM, "x0_it_mring013", GetStartingLocation());
|
|
if (!GetIsObjectValid(oPlc) || !GetIsObjectValid(oItem))
|
|
{
|
|
WriteTimestampedLogEntry("NWNX_SQL test: Failed to create objects..");
|
|
}
|
|
else
|
|
{
|
|
object oTmp = GetFirstItemInInventory(oPlc);
|
|
while (GetIsObjectValid(oTmp))
|
|
{
|
|
WriteTimestampedLogEntry("NWNX_SQL Destroying auto created object " + GetTag(oTmp));
|
|
DestroyObject(oTmp);
|
|
oTmp = GetNextItemInInventory(oPlc);
|
|
}
|
|
|
|
string test2 = "";
|
|
if (db_type == "MYSQL" || db_type == "SQLITE")
|
|
{
|
|
test2="INSERT INTO sql_test(colInt, colFloat, colStr, colObjId, colObj) VALUES(1337,0.0,'xxx',1337,?)";
|
|
}
|
|
if (db_type == "POSTGRESQL")
|
|
{
|
|
test2="INSERT INTO sql_test(colInt, colFloat, colStr, colObjId, colObj) VALUES(1337,0.0,'xxx',1337,$1)";
|
|
}
|
|
|
|
NWNX_SQL_PrepareQuery(test2);
|
|
|
|
NWNX_SQL_PreparedObjectFull(0, oItem);
|
|
b = NWNX_SQL_ExecutePreparedQuery();
|
|
NWNX_Tests_Report("NWNX_SQL", "Insert item full", b);
|
|
|
|
b = NWNX_SQL_ExecuteQuery("SELECT colObj FROM sql_test WHERE colInt=1337");
|
|
NWNX_Tests_Report("NWNX_SQL", "Select item", b);
|
|
|
|
if (NWNX_SQL_ReadyToReadNextRow())
|
|
{
|
|
NWNX_SQL_ReadNextRow();
|
|
|
|
object oItem2 = NWNX_SQL_ReadFullObjectInActiveRow(0, oPlc);
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadFullObject Item", GetIsObjectValid(oItem2));
|
|
NWNX_Tests_Report("NWNX_SQL", "Deserialized to placeable's inventory", oItem2 == GetFirstItemInInventory(oPlc));
|
|
NWNX_Tests_Report("NWNX_SQL", "Deserialized to placeable's inventory - possessor", GetItemPossessor(oItem2) == oPlc);
|
|
|
|
object oItem3 = NWNX_SQL_ReadFullObjectInActiveRow(0, GetArea(oPlc), v.x, v.y, v.z);
|
|
NWNX_Tests_Report("NWNX_SQL", "Deserialized to area", GetArea(oItem3) == GetArea(oPlc));
|
|
|
|
object oItem4 = NWNX_SQL_ReadFullObjectInActiveRow(0, o);
|
|
NWNX_Tests_Report("NWNX_SQL", "Deserialized to creature's inventory - possessor", GetItemPossessor(oItem4) == o);
|
|
}
|
|
else
|
|
{
|
|
WriteTimestampedLogEntry("NWNX_SQL not ready to read item");
|
|
}
|
|
|
|
}
|
|
|
|
int STRESS_CNT = 10;
|
|
|
|
WriteTimestampedLogEntry("NWNX_SQL stress test.");
|
|
NWNX_SQL_ExecuteQuery("create table stress_test ( i_key int, i_int int, s_text varchar(8))");
|
|
int i;
|
|
// Brute force some inserts
|
|
for ( i=1 ; i<=STRESS_CNT ; i++ ) // Generate 1000 rows.
|
|
{
|
|
// Simulates the existing NWNX2 ODBC way of generating SQL.
|
|
NWNX_SQL_ExecuteQuery("insert into stress_test values ( " + IntToString(i) + ", " + IntToString(i*2) + ", '" + IntToString(i*100) + "')");
|
|
}
|
|
NWNX_SQL_ExecuteQuery("delete from stress_test where i_key > 0");
|
|
int res = NWNX_SQL_GetAffectedRows();
|
|
WriteTimestampedLogEntry("Deleted " + IntToString(res) + " rows.");
|
|
report ("Delete rows", res == STRESS_CNT);
|
|
|
|
// now do some elegant inserts
|
|
string test3 = "";
|
|
if (db_type == "MYSQL" || db_type == "SQLITE")
|
|
{
|
|
test3 = "insert into stress_test values ( ?, ?, ? )";
|
|
}
|
|
if (db_type == "POSTGRESQL")
|
|
{
|
|
test3 = "insert into stress_test values ( $1, $2, $3 )";
|
|
}
|
|
|
|
NWNX_SQL_PrepareQuery(test3);
|
|
for ( i = 1 ; i <= STRESS_CNT ; i++ )
|
|
{
|
|
NWNX_SQL_PreparedInt(0, i);
|
|
NWNX_SQL_PreparedInt(1, i*2);
|
|
NWNX_SQL_PreparedString(2, IntToString(i*100));
|
|
b = NWNX_SQL_ExecutePreparedQuery();
|
|
NWNX_Tests_Report("NWNX_SQL", "Elegant Looping ExecutePreparedQuery", b);
|
|
}
|
|
NWNX_SQL_ExecuteQuery("delete from stress_test where i_key > 0");
|
|
res = NWNX_SQL_GetAffectedRows();
|
|
WriteTimestampedLogEntry("Deleted " + IntToString(res) + " rows.");
|
|
NWNX_Tests_Report("Delete rows", res == STRESS_CNT);
|
|
|
|
// Test some error output.
|
|
b = NWNX_SQL_ExecuteQuery("create table error_test (col varchar(10))");
|
|
NWNX_Tests_Report("Test Table Create", b);
|
|
|
|
b = NWNX_SQL_ExecuteQuery("insert into error_test values('abcdefghij')");
|
|
NWNX_Tests_Report("good insert", b);
|
|
|
|
if (db_type != "SQLITE")
|
|
{// SQLite doesn't care about size constraints of columns
|
|
b = NWNX_SQL_ExecuteQuery("insert into error_test values('abcde000fghij')");
|
|
report ("bad insert", !b);
|
|
if (!b) {
|
|
WriteTimestampedLogEntry("There should be an error a couple rows up.");
|
|
}
|
|
}
|
|
|
|
string test4 = "";
|
|
if (db_type == "MYSQL" || db_type == "SQLITE")
|
|
{
|
|
test3 = "insert into error_test values ( ? )";
|
|
}
|
|
if (db_type == "POSTGRESQL")
|
|
{
|
|
test3 = "insert into error_test values ( $1 )";
|
|
}
|
|
NWNX_SQL_PrepareQuery(test3);
|
|
NWNX_SQL_PreparedString(100, "lala"); // out of bounds, must not crash.
|
|
|
|
NWNX_Tests_Report("NWNX_SQL", "Negative prepare query", NWNX_SQL_PrepareQuery("not a valid query!") == 0);
|
|
NWNX_Tests_Report("NWNX_SQL", "GetLastError", NWNX_SQL_GetLastError() != "");
|
|
|
|
// Test with null values
|
|
NWNX_SQL_ExecuteQuery("INSERT INTO sql_test(colInt, colFloat, colStr, colObjId, colObj) VALUES(5121, null, null, null, null)");
|
|
NWNX_Tests_Report("NWNX_SQL", "Select null", NWNX_SQL_ExecuteQuery("SELECT * FROM sql_test WHERE colInt=5121"));
|
|
if (NWNX_SQL_ReadyToReadNextRow())
|
|
{
|
|
NWNX_SQL_ReadNextRow();
|
|
int n = StringToInt(NWNX_SQL_ReadDataInActiveRow(0));
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadInt", n == 5121);
|
|
float f = StringToFloat(NWNX_SQL_ReadDataInActiveRow(1));
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadFloat", f == 0.0);
|
|
string s = NWNX_SQL_ReadDataInActiveRow(2);
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadString", s == "");
|
|
|
|
string sObjId = NWNX_SQL_ReadDataInActiveRow(3); // In base 10
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadObjectId", sObjId == "");
|
|
|
|
object obj = NWNX_SQL_ReadFullObjectInActiveRow(4);
|
|
NWNX_Tests_Report("NWNX_SQL", "ReadFullObject", obj == OBJECT_INVALID);
|
|
}
|
|
|
|
cleanup();
|
|
WriteTimestampedLogEntry("Testing database " + db_type + " complete.");
|
|
WriteTimestampedLogEntry("NWNX_SQL unit tests end.");
|
|
}
|