#pragma semicolon 1 #include #include #include #define VERSION "0.0.2" public Plugin myinfo = { name = "SMJansson, Test, Create JSON", author = "Thrawn", description = "", version = VERSION, }; public void OnPluginStart() { CreateConVar("sm_smjansson_test_version", VERSION, "Tests all SMJansson natives.", FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD); bool bStepSuccess = false; StringMap hTest = Test_New(103); Test_Ok(hTest, LibraryExists("jansson"), "Library is loaded"); Handle hObj = json_object(); Test_IsNot(hTest, hObj, INVALID_HANDLE, "Creating JSON Object"); Test_Ok(hTest, json_is_object(hObj), "Type is Object"); Handle hString = json_string("value"); Test_IsNot(hTest, hString, INVALID_HANDLE, "Creating JSON String"); Test_Ok(hTest, json_is_string(hString), "Type is String"); char sString[32]; json_string_value(hString, sString, sizeof(sString)); Test_Is_String(hTest, sString, "value", "Checking created JSON String value"); Test_Ok(hTest, json_string_set(hString, "The answer is 42"), "Modifying string value"); json_string_value(hString, sString, sizeof(sString)); Test_Is_String(hTest, sString, "The answer is 42", "Checking modified JSON String value"); bStepSuccess = json_object_set(hObj, "__String", hString); Test_Ok(hTest, bStepSuccess, "Attaching modified String to root object"); delete hString; float fNumberValue; float fReal; Handle hReal = json_real(1.23456789); Test_IsNot(hTest, hReal, INVALID_HANDLE, "Creating JSON Real"); Test_Is(hTest, json_typeof(hReal), view_as(JSON_REAL), "Type is Real"); fReal = json_real_value(hReal); Test_Is_Float(hTest, fReal, 1.23456789, "Checking created JSON Real value"); fNumberValue = json_number_value(hReal); Test_Is_Float(hTest, fReal, 1.23456789, "Checking result of json_number_value"); Test_Ok(hTest, json_real_set(hReal, -444.556), "Modifying real value"); fReal = json_real_value(hReal); Test_Is_Float(hTest, fReal, -444.556, "Checking modified JSON Real value"); fNumberValue = json_number_value(hReal); Test_Is_Float(hTest, fReal, -444.556, "Checking result of json_number_value"); bStepSuccess = json_object_set(hObj, "__Float", hReal); Test_Ok(hTest, bStepSuccess, "Attaching modified Real to root object"); delete hReal; int iInteger; Handle hInteger = json_integer(42); Test_IsNot(hTest, hInteger, INVALID_HANDLE, "Creating JSON Integer"); Test_Is(hTest, json_typeof(hInteger), view_as(JSON_INTEGER), "Type is Integer"); iInteger = json_integer_value(hInteger); Test_Is(hTest, iInteger, 42, "Checking created JSON Integer value"); fNumberValue = json_number_value(hInteger); Test_Is_Float(hTest, fNumberValue, 42.0, "Checking result of json_number_value"); Test_Ok(hTest, json_integer_set(hInteger, 1337), "Modifying integer value"); iInteger = json_integer_value(hInteger); Test_Is(hTest, iInteger, 1337, "Checking modified JSON Integer value"); fNumberValue = json_number_value(hInteger); Test_Is_Float(hTest, fNumberValue, 1337.0, "Checking result of json_number_value"); bStepSuccess = json_object_set(hObj, "__Integer", hInteger); Test_Ok(hTest, bStepSuccess, "Attaching modified Integer to root object"); Test_Is(hTest, json_object_size(hObj), 3, "Object has the correct size"); delete hInteger; char sShouldBe[128] = "{\"__Float\": -444.55599975585938, \"__String\": \"The answer is 42\", \"__Integer\": 1337}"; char sJSON[4096]; json_dump(hObj, sJSON, sizeof(sJSON), 0); Test_Is_String(hTest, sJSON, sShouldBe, "Created JSON is ok"); Handle hObjNested = json_object(); bStepSuccess = json_object_set(hObj, "__NestedObject", hObjNested); Test_Ok(hTest, bStepSuccess, "Attaching new Object to root object"); Test_Is(hTest, json_object_size(hObj), 4, "Object has the correct size"); bStepSuccess = json_object_set_new(hObjNested, "__NestedString", json_string("i am nested")); Test_Ok(hTest, bStepSuccess, "Attaching new String to nested object (using reference stealing)"); Test_Ok(hTest, json_object_del(hObj, "__Float"), "Deleting __Float element from root object"); Test_Is(hTest, json_object_size(hObj), 3, "Object has the correct size"); Handle hArray = json_array(); Test_IsNot(hTest, hArray, INVALID_HANDLE, "Creating JSON Array"); Test_Is(hTest, json_typeof(hArray), view_as(JSON_ARRAY), "Type is Array"); Handle hFirst_String = json_string("1"); Handle hSecond_Float = json_real(2.0); Handle hThird_Integer = json_integer(3); Handle hFourth_String = json_string("4"); Test_Ok(hTest, json_array_append(hArray, hFirst_String), "Appending String to Array"); delete hFirst_String; Test_Is(hTest, json_array_size(hArray), 1, "Array has correct size"); Test_Ok(hTest, json_array_append(hArray, hSecond_Float), "Appending float to Array"); delete hSecond_Float; Test_Is(hTest, json_array_size(hArray), 2, "Array has correct size"); Test_Ok(hTest, json_array_insert(hArray, 0, hThird_Integer), "Inserting Integer at position 0"); delete hThird_Integer; Test_Is(hTest, json_array_size(hArray), 3, "Array has correct size"); Test_Ok(hTest, json_array_set(hArray, 1, hFourth_String), "Setting String at position 1"); delete hFourth_String; Test_Is(hTest, json_array_size(hArray), 3, "Array has correct size"); bStepSuccess = json_object_set(hObjNested, "__Array", hArray); Test_Ok(hTest, bStepSuccess, "Attaching Array to nested object"); delete hObjNested; PrintToServer(" - Creating the same Array using reference stealing"); Handle hArrayStealing = json_array(); Test_Ok(hTest, json_array_append_new(hArrayStealing, json_string("1")), "Appending new String to Array"); Test_Ok(hTest, json_array_append_new(hArrayStealing, json_real(2.0)), "Appending new float to Array"); Test_Ok(hTest, json_array_insert_new(hArrayStealing, 0, json_integer(3)), "Inserting new Integer at position 0"); Test_Ok(hTest, json_array_set_new(hArrayStealing, 1, json_string("4")), "Setting new String at position 1"); Test_Ok(hTest, json_equal(hArray, hArrayStealing), "Arrays are equal."); delete hArrayStealing; delete hArray; DeleteFile("testoutput.json"); bStepSuccess = json_dump_file(hObj, "testoutput.json", 2); Test_Ok(hTest, bStepSuccess, "File written without errors"); Test_Ok(hTest, FileExists("testoutput.json"), "Testoutput file exists"); // Reload the written file Handle hReloaded = json_load_file("testoutput.json"); Test_IsNot(hTest, hReloaded, INVALID_HANDLE, "Loading JSON from file."); Test_Ok(hTest, json_equal(hReloaded, hObj), "Written file and data in memory are equal"); // Iterate over the reloaded file Handle hIterator = json_object_iter(hReloaded); Test_IsNot(hTest, hIterator, INVALID_HANDLE, "Creating an iterator for the reloaded object."); // Expecting three values in random order // Use a trie to look em up and delete them from it -> afterwards size must be 0 StringMap hTestTrie = new StringMap(); hTestTrie.SetValue("__String", view_as(JSON_STRING)); hTestTrie.SetValue("__Integer", view_as(JSON_INTEGER)); hTestTrie.SetValue("__NestedObject", view_as(JSON_OBJECT)); while (hIterator != null) { char sKey[128]; json_object_iter_key(hIterator, sKey, sizeof(sKey)); Handle hValue = json_object_iter_value(hIterator); json_type xType = json_typeof(hValue); char sType[32]; Stringify_json_type(xType, sType, sizeof(sType)); json_type xShouldBeType; hTestTrie.GetValue(sKey, xShouldBeType); PrintToServer(" - Found key: %s (Type: %s)", sKey, sType); Test_Is(hTest, xShouldBeType, view_as(xType), "Type is correct"); hTestTrie.Remove(sKey); if (xType == JSON_INTEGER) { Handle hIntegerOverwrite = json_integer(9001); Test_Ok(hTest, json_object_iter_set(hReloaded, hIterator, hIntegerOverwrite), "Overwriting integer value at iterator position"); delete hIntegerOverwrite; } if (xType == JSON_STRING) { Test_Ok(hTest, json_object_iter_set_new(hReloaded, hIterator, json_string("What is the \"Hitchhiker's guide to the galaxy\"?")), "Overwriting string value at iterator position (using reference stealing)"); } if (xType == JSON_OBJECT) { StringMap hTestTrieForArray = new StringMap(); hTestTrieForArray.SetValue("String", 0); hTestTrieForArray.SetValue("Integer", 0); hTestTrieForArray.SetValue("Real", 0); Handle hReloadedArray = json_object_get(hValue, "__Array"); Test_IsNot(hTest, hReloadedArray, INVALID_HANDLE, "Getting JSON Array from reloaded object"); Test_Is(hTest, json_array_size(hReloadedArray), 3, "Array has correct size"); for (int iElement = 0; iElement < json_array_size(hReloadedArray); iElement++) { Handle hElement = json_array_get(hReloadedArray, iElement); char sArrayType[32]; Stringify_json_type(json_typeof(hElement), sArrayType, sizeof(sArrayType)); PrintToServer(" - Found element with type: %s", sArrayType); hTestTrieForArray.Remove(sArrayType); delete hElement; } Test_Is(hTest, hTestTrieForArray.Size, 0, "Looped over all array elements"); delete hTestTrieForArray; Test_Ok(hTest, json_array_remove(hReloadedArray, 2), "Deleting 3rd element from array"); Test_Is(hTest, json_array_size(hReloadedArray), 2, "Array has correct size"); Handle hArrayForExtending = json_array(); Handle hStringForExtension = json_string("Extension 1"); Handle hStringForExtension2 = json_string("Extension 2"); json_array_append(hArrayForExtending, hStringForExtension); json_array_append(hArrayForExtending, hStringForExtension2); delete hStringForExtension; delete hStringForExtension2; Test_Ok(hTest, json_array_extend(hReloadedArray, hArrayForExtending), "Extending array"); Test_Is(hTest, json_array_size(hReloadedArray), 4, "Array has correct size"); Test_Ok(hTest, json_array_clear(hArrayForExtending), "Clearing array"); Test_Is(hTest, json_array_size(hArrayForExtending), 0, "Array is empty"); delete hArrayForExtending; delete hReloadedArray; } delete hValue; hIterator = json_object_iter_next(hReloaded, hIterator); } Test_Is(hTest, hTestTrie.Size, 0, "Iterator looped over all keys"); delete hTestTrie; Test_OkNot(hTest, json_equal(hReloaded, hObj), "Written file and data in memory are not equal anymore"); PrintToServer(" - Creating the same object using json_pack"); ArrayList hParams = new ArrayList(64); hParams.PushString("__String"); hParams.PushString("What is the \"Hitchhiker's guide to the galaxy\"?"); hParams.PushString("__Integer"); hParams.Push(9001); hParams.PushString("__NestedObject"); hParams.PushString("__NestedString"); hParams.PushString("i am nested"); hParams.PushString("__Array"); hParams.Push(3); hParams.PushString("4"); hParams.PushString("Extension 1"); hParams.PushString("Extension 2"); Handle hPacked = json_pack("{ss, s:is{sss:[isss]}}", hParams); delete hParams; Test_Ok(hTest, json_equal(hReloaded, hPacked), "Packed JSON is equal to manually created JSON"); delete hPacked; PrintToServer(" - Testing all json_pack values"); ArrayList hParamsAll = new ArrayList(64); hParamsAll.PushString("String"); hParamsAll.Push(42); hParamsAll.Push(13.37); hParamsAll.Push(20001.333); hParamsAll.Push(true); hParamsAll.Push(false); Handle hPackAll = json_pack("[sifrbnb]", hParamsAll); Test_Ok(hTest, json_is_array(hPackAll), "Packed JSON is an array"); char sElementOne[32]; json_array_get_string(hPackAll, 0, sElementOne, sizeof(sElementOne)); Test_Is_String(hTest, sElementOne, "String", "Element 1 has the correct string value"); Test_Is(hTest, json_array_get_int(hPackAll, 1), 42, "Element 2 has the correct integer value"); Test_Is(hTest, json_array_get_float(hPackAll, 2), 13.37, "Element 3 has the correct float value"); Test_Is(hTest, json_array_get_float(hPackAll, 3), 20001.333, "Element 4 has the correct float value"); Test_Is(hTest, json_array_get_bool(hPackAll, 4), true, "Element 5 is boolean true."); Handle hElementFive = json_array_get(hPackAll, 5); Test_Is(hTest, json_typeof(hElementFive), JSON_NULL, "Element 6 is null."); delete hElementFive; Test_Is(hTest, json_array_get_bool(hPackAll, 6), false, "Element 7 is boolean false."); delete hParamsAll; PrintToServer(" - Creating new object with 4 keys via load"); Handle hObjManipulation = json_load("{\"A\":1,\"B\":2,\"C\":3,\"D\":4}"); Test_Ok(hTest, json_object_del(hObjManipulation, "D"), "Deleting element from object"); Test_Is(hTest, json_object_size(hObjManipulation), 3, "Object size is correct"); PrintToServer(" - Creating new object to update the previous one"); Handle hObjUpdate = json_load("{\"A\":10,\"B\":20,\"C\":30,\"D\":40,\"E\":50,\"F\":60,\"G\":70}"); Test_Ok(hTest, json_object_update_existing(hObjManipulation, hObjUpdate), "Updating existing keys"); Handle hReadC = json_object_get(hObjManipulation, "C"); Test_Is(hTest, json_integer_value(hReadC), 30, "Element update successful"); Test_Is(hTest, json_object_size(hObjManipulation), 3, "Object size is correct"); delete hReadC; Test_Ok(hTest, json_object_update_missing(hObjManipulation, hObjUpdate), "Updating missing keys"); Handle hReadF = json_object_get(hObjManipulation, "F"); Test_Is(hTest, json_integer_value(hReadF), 60, "Element insertion via update successful"); Test_Is(hTest, json_object_size(hObjManipulation), 7, "Object size is correct"); delete hReadF; Test_Ok(hTest, json_object_clear(hObjManipulation), "Clearing new object"); Test_Is(hTest, json_object_size(hObjManipulation), 0, "Object is empty"); PrintToServer(" - Adding one of the original four keys"); Handle hBNew = json_integer(2); json_object_set(hObjManipulation, "B", hBNew); Test_Ok(hTest, json_object_update(hObjManipulation, hObjUpdate), "Updating all keys"); delete hBNew; delete hObjUpdate; Handle hReadB = json_object_get(hObjManipulation, "B"); Test_Is(hTest, json_integer_value(hReadB), 20, "Element update successful"); delete hReadB; Test_Is(hTest, json_object_size(hObjManipulation), 7, "Object size is correct"); PrintToServer(" - Creating and adding an array to the object"); Handle hCopyArray = json_array(); Handle hNoMoreVariableNames = json_string("no more!"); Handle hEvenLessVariableNames = json_string("less n less!"); json_array_append(hCopyArray, hNoMoreVariableNames); json_array_append(hCopyArray, hEvenLessVariableNames); json_object_set(hObjManipulation, "Array", hCopyArray); Handle hCopy = json_copy(hObjManipulation); Test_IsNot(hTest, hCopy, INVALID_HANDLE, "Creating copy of JSON Object"); Test_Is(hTest, json_object_size(hCopy), 8, "Object size is correct"); Test_Ok(hTest, json_equal(hCopy, hObjManipulation), "Objects are equal"); PrintToServer(" - Modifying the array of the original Object"); Handle hEmptyVariableNames = json_string("empty!"); json_array_append(hCopyArray, hEmptyVariableNames); Test_Ok(hTest, json_equal(hCopy, hObjManipulation), "Content of copy is still identical (was a shallow copy)"); Handle hDeepCopy = json_deep_copy(hObjManipulation); Test_IsNot(hTest, hDeepCopy, INVALID_HANDLE, "Creating deep copy of JSON Object"); Test_Is(hTest, json_object_size(hDeepCopy), 8, "Object size is correct"); Test_Ok(hTest, json_equal(hDeepCopy, hObjManipulation), "Objects are equal"); PrintToServer(" - Modifying the array of the original Object"); Handle hDeadVariableNames = json_string("dead!"); json_array_append(hCopyArray, hDeadVariableNames); delete hCopyArray; Test_OkNot(hTest, json_equal(hDeepCopy, hObjManipulation), "Content of copy is not identical anymore (was a deep copy)"); Handle hBooleanObject = json_object(); json_object_set_new(hBooleanObject, "true1", json_true()); json_object_set_new(hBooleanObject, "false1", json_false()); json_object_set_new(hBooleanObject, "true2", json_boolean(true)); json_object_set_new(hBooleanObject, "false2", json_boolean(false)); json_object_set_new(hBooleanObject, "null", json_null()); char sBooleanObjectDump[4096]; json_dump(hBooleanObject, sBooleanObjectDump, sizeof(sBooleanObjectDump), 0); char sBooleanShouldBe[4096] = "{\"false2\": false, \"true1\": true, \"false1\": false, \"true2\": true, \"null\": null}"; Test_Is_String(hTest, sBooleanObjectDump, sBooleanShouldBe, "Created JSON matches"); delete hBooleanObject; char sErrorMsg[255]; int iLine = -1; int iColumn = -1; Handle hNoObj = json_load_ex("{\"apple\": 3 \"banana\": 0, \"error\": \"missing a comma\"}", sErrorMsg, sizeof(sErrorMsg), iLine, iColumn); if (hNoObj == null) { Test_Is(hTest, iLine, 1, "Correct error line"); Test_Is(hTest, iColumn, 20, "Correct error column"); Test_Ok(hTest, strlen(sErrorMsg) > 0, "Error message is not empty"); } else { delete hNoObj; } json_dump(hObj, sJSON, sizeof(sJSON)); PrintToServer("\nJSON 1:\n-------------\n%s\n-------------\n", sJSON); char sJSONReloaded[4096]; json_dump(hReloaded, sJSONReloaded, sizeof(sJSONReloaded), 2); PrintToServer("JSON 2:\n-------------\n%s\n-------------\n", sJSONReloaded); char sJSONManipulated[4096]; json_dump(hObjManipulation, sJSONManipulated, sizeof(sJSONManipulated), 0); PrintToServer("JSON 3:\n-------------\n%s\n-------------\n", sJSONManipulated); PrintToServer("JSON 4:\n-------------\n%s\n-------------\n", sBooleanObjectDump); char sJSONPackAll[4096]; json_dump(hPackAll, sJSONPackAll, sizeof(sJSONPackAll), 4); PrintToServer("JSON 5:\n-------------\n%s\n-------------\n", sJSONPackAll); delete hPackAll; delete hObj; delete hObjManipulation; delete hReloaded; // Finish testing Test_End(hTest); delete hTest; }