diff --git a/DesktopEditor/doctrenderer/test/js_internal/main.cpp b/DesktopEditor/doctrenderer/test/js_internal/main.cpp index 5ebc571c58..2619ea5187 100644 --- a/DesktopEditor/doctrenderer/test/js_internal/main.cpp +++ b/DesktopEditor/doctrenderer/test/js_internal/main.cpp @@ -1,11 +1,17 @@ -#include "gtest/gtest.h" - #include "js_internal/js_base.h" +#ifdef JS_INTERNAL_GOOGLE_TEST +#include "gtest/gtest.h" #include +#else +#include +#endif using namespace NSJSBase; +#ifdef JS_INTERNAL_GOOGLE_TEST +// CJSObject::getPropertyNames() tests +// run with "--gtest_filter=CGetPropertyNamesTest.*" to run only this test suite class CGetPropertyNamesTest : public testing::Test { public: @@ -122,3 +128,190 @@ TEST_F(CGetPropertyNamesTest, object_with_prototype) std::vector expected2 = {"name", "greet"}; EXPECT_TRUE(compare(result2, expected2)) << printInfo("Actual: ", result2) << printInfo("Expected: ", expected2); } + +// CJSContext::JSON_Stringify() tests +// run with "--gtest_filter=CJSONStringifyTest.*" to run only this test suite +class CJSONStringifyTest : public testing::Test +{ +public: + void SetUp() override + { + // create and enter context + m_pContext = new CJSContext(); + m_pContext->Enter(); + } + + void TearDown() override + { + m_pContext->Exit(); + } + + JSSmart createObject(const std::string& objLiteral) + { + return m_pContext->runScript("(() => { return " + objLiteral + ";})();")->toObject(); + } + +public: + JSSmart m_pContext; +}; + +TEST_F(CJSONStringifyTest, undefined) +{ + JSSmart jsValue = CJSContext::createUndefined(); + std::string sRes = m_pContext->JSON_Stringify(jsValue); + EXPECT_TRUE(sRes.empty()); +} + +TEST_F(CJSONStringifyTest, null) +{ + JSSmart jsValue = CJSContext::createNull(); + std::string sRes = m_pContext->JSON_Stringify(jsValue); + EXPECT_EQ(sRes, "null"); +} + +TEST_F(CJSONStringifyTest, numbers) +{ + JSSmart jsValue = CJSContext::createInt(42); + std::string sRes = m_pContext->JSON_Stringify(jsValue); + EXPECT_EQ(sRes, "42"); + + jsValue = CJSContext::createUInt(7); + sRes = m_pContext->JSON_Stringify(jsValue); + EXPECT_EQ(sRes, "7"); + + jsValue = CJSContext::createDouble(3.1415926535); + sRes = m_pContext->JSON_Stringify(jsValue); + EXPECT_EQ(sRes, "3.1415926535"); +} + +TEST_F(CJSONStringifyTest, strings) +{ + JSSmart jsValue = CJSContext::createString(""); + std::string sRes = m_pContext->JSON_Stringify(jsValue); + EXPECT_EQ(sRes, "\"\""); + + jsValue = CJSContext::createString("foo bar"); + sRes = m_pContext->JSON_Stringify(jsValue); + EXPECT_EQ(sRes, "\"foo bar\""); +} + +TEST_F(CJSONStringifyTest, arrays) +{ + JSSmart jsArr = CJSContext::createArray(0); + std::string sRes = m_pContext->JSON_Stringify(jsArr->toValue()); + EXPECT_EQ(sRes, "[]"); + + jsArr = CJSContext::createArray(4); + jsArr->set(0, 42); + // inner array + JSSmart jsArrInner = CJSContext::createArray(2); + jsArrInner->set(0, CJSContext::createString("foo")); + jsArrInner->set(1, CJSContext::createDouble(2.71828)); + jsArr->set(1, jsArrInner->toValue()); + + jsArr->set(2, CJSContext::createNull()); + jsArr->set(3, CJSContext::createUndefined()); + sRes = m_pContext->JSON_Stringify(jsArr->toValue()); + EXPECT_EQ(sRes, "[42,[\"foo\",2.71828],null,null]"); +} + +TEST_F(CJSONStringifyTest, typed_arrays) +{ + BYTE* data = NSAllocator::Alloc(4); + data[0] = 0x1A; + data[1] = 0x54; + data[2] = 0xFE; + data[3] = 0xFF; + JSSmart jsTypedArr = CJSContext::createUint8Array(data, 4, false); + + std::string sRes = m_pContext->JSON_Stringify(jsTypedArr->toValue()); + EXPECT_EQ(sRes, "{\"0\":26,\"1\":84,\"2\":254,\"3\":255}"); + NSAllocator::Free(data, 4); +} + +TEST_F(CJSONStringifyTest, empty_object) +{ + JSSmart jsObj = CJSContext::createObject(); + std::string sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{}"); + + jsObj->set("number", CJSContext::createInt(42)); + jsObj->set("name", CJSContext::createString("foo")); + sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{\"number\":42,\"name\":\"foo\"}"); +} + +TEST_F(CJSONStringifyTest, normal_object) +{ + JSSmart jsObj = createObject("{number: 42, name: 'foo', arr: [1, 'abc', 2, 3], func() { return 'bar'; }}"); + std::string sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{\"number\":42,\"name\":\"foo\",\"arr\":[1,\"abc\",2,3]}"); +} + +TEST_F(CJSONStringifyTest, only_one_function_in_object) +{ + JSSmart jsObj = createObject("{add(a, b) { return a + b; }}"); + std::string sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{}"); +} + +TEST_F(CJSONStringifyTest, inner_object) +{ + JSSmart jsObj = createObject("{inner: {number: 42, name: 'foo'}, own: 'bar'}"); + std::string sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{\"inner\":{\"number\":42,\"name\":\"foo\"},\"own\":\"bar\"}"); +} + +TEST_F(CJSONStringifyTest, object_with_null_and_undefined_properties) +{ + JSSmart jsObj = createObject("{number: null, name: undefined, func() { return 'bar'; }}"); + std::string sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{\"number\":null}"); +} + +TEST_F(CJSONStringifyTest, object_with_only_undefined_properties) +{ + JSSmart jsObj = createObject("{foo: undefined, bar: undefined}"); + std::string sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{}"); +} + +TEST_F(CJSONStringifyTest, array_as_object) +{ + JSSmart jsObj = createObject("{0: 4, 1: 2, 2: undefined, 3: 'foo', 42: 'bar'}"); + std::string sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{\"0\":4,\"1\":2,\"3\":\"foo\",\"42\":\"bar\"}"); +} + +TEST_F(CJSONStringifyTest, object_with_prototype) +{ + m_pContext->runScript( + "var personPrototype = { age: 42, greet() { return 'Hello, world!'; } };" + "function Person(name) { this.name = name; }" + ); + + JSSmart jsObj = m_pContext->runScript("new Person('Foo');")->toObject(); + std::string sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + EXPECT_EQ(sRes, "{\"name\":\"Foo\"}"); + + m_pContext->runScript("Object.assign(Person.prototype, personPrototype);"); + sRes = m_pContext->JSON_Stringify(jsObj->toValue()); + // expect the same result, because JSON.stringify does not preserve any of the not-owned properties of the object + EXPECT_EQ(sRes, "{\"name\":\"Foo\"}"); +} + +#else +int main() +{ + JSSmart pContext = new CJSContext(); + CJSContextScope scope(pContext); + + JSSmart jsObj = CJSContext::createObject(); + jsObj->set("number", CJSContext::createInt(42)); + jsObj->set("name", CJSContext::createString("foo")); + + std::cout << pContext->JSON_Stringify(jsObj->toValue()) << std::endl; + + return 0; +} +#endif // JS_INTERNAL_GOOGLE_TEST diff --git a/DesktopEditor/doctrenderer/test/js_internal/test.pro b/DesktopEditor/doctrenderer/test/js_internal/test.pro index e8554bc81f..94f7eb759b 100644 --- a/DesktopEditor/doctrenderer/test/js_internal/test.pro +++ b/DesktopEditor/doctrenderer/test/js_internal/test.pro @@ -1,32 +1,39 @@ -QT -= core -QT -= gui +QT -= core +QT -= gui -TARGET = test -CONFIG += console -CONFIG -= app_bundle +TARGET = test +CONFIG += console +CONFIG -= app_bundle TEMPLATE = app -CONFIG += core_static_link_libstd +CONFIG += core_static_link_libstd CORE_ROOT_DIR = $$PWD/../../../../../core CORE_3DPARTY_DIR = $$CORE_ROOT_DIR/Common/3dParty PWD_ROOT_DIR = $$PWD include($$CORE_ROOT_DIR/Common/base.pri) -include($$CORE_3DPARTY_DIR/googletest/googletest.pri) + +# Comment to inspect custom main +# Uncomment to run google tests +CONFIG += js_internal_google_test + +js_internal_google_test { + include($$CORE_3DPARTY_DIR/googletest/googletest.pri) + DEFINES += JS_INTERNAL_GOOGLE_TEST +} DESTDIR = $$PWD/build -INCLUDEPATH += $$CORE_ROOT_DIR/DesktopEditor/doctrenderer +INCLUDEPATH += ../.. ADD_DEPENDENCY(doctrenderer) core_linux { - LIBS += -Wl,-unresolved-symbols=ignore-in-shared-libs - LIBS += -ldl + LIBS += -Wl,-unresolved-symbols=ignore-in-shared-libs + LIBS += -ldl } SOURCES += \ main.cpp -