From 48d19919cc82f637ee96873f81c957cdf9b84127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 27 Oct 2010 13:44:11 +0200 Subject: mkspecs: Emit warning when including g++.conf directly 86636e0c4ab91bfb6 refactored the mkspecs, but didn't account for people with their own mkspec who would still include g++.conf directly. We now print a warning if this situation is detected, and explain to the user how they can fix their mkspec. For convenience we redirect g++.conf to g++-unix.conf so that people's mkspecs will still work. Reviewed-by: Marius Storm-Olsen --- mkspecs/common/g++-base.conf | 23 ++++++++++++ mkspecs/common/g++-mac.conf | 32 ---------------- mkspecs/common/g++-macx.conf | 32 ++++++++++++++++ mkspecs/common/g++-unix.conf | 2 +- mkspecs/common/g++.conf | 24 +++--------- mkspecs/common/gcc-base-mac.conf | 43 ---------------------- mkspecs/common/gcc-base-macx.conf | 43 ++++++++++++++++++++++ mkspecs/common/gcc-base.conf | 10 ++--- mkspecs/macx-g++/qmake.conf | 4 +- mkspecs/macx-g++40/qmake.conf | 4 +- mkspecs/macx-g++42/qmake.conf | 4 +- mkspecs/macx-llvm/qmake.conf | 2 +- mkspecs/macx-xcode/qmake.conf | 4 +- mkspecs/symbian-gcce/qmake.conf | 3 +- mkspecs/unsupported/macx-clang/qmake.conf | 2 +- mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf | 1 - 16 files changed, 122 insertions(+), 111 deletions(-) create mode 100644 mkspecs/common/g++-base.conf delete mode 100644 mkspecs/common/g++-mac.conf create mode 100644 mkspecs/common/g++-macx.conf delete mode 100644 mkspecs/common/gcc-base-mac.conf create mode 100644 mkspecs/common/gcc-base-macx.conf diff --git a/mkspecs/common/g++-base.conf b/mkspecs/common/g++-base.conf new file mode 100644 index 0000000..d73b38f --- /dev/null +++ b/mkspecs/common/g++-base.conf @@ -0,0 +1,23 @@ +# +# Qmake configuration for the GNU C++ compiler +# +# Before making changes to this file, please read the comment in +# gcc-base.conf, to make sure the change goes in the right place. +# +# To verify that your change has the desired effect on the final configuration +# you can use the manual test in tests/manual/mkspecs. +# + +QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -g + +QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO + +QMAKE_LINK_C = $$QMAKE_CC +QMAKE_LINK_C_SHLIB = $$QMAKE_CC + +QMAKE_PCH_OUTPUT_EXT = .gch + +QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} +QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE} +QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} +QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE diff --git a/mkspecs/common/g++-mac.conf b/mkspecs/common/g++-mac.conf deleted file mode 100644 index bcfd9aa..0000000 --- a/mkspecs/common/g++-mac.conf +++ /dev/null @@ -1,32 +0,0 @@ -# -# Qmake configuration for the GNU C++ compiler on Mac OS X -# -# Before making changes to this file, please read the comment in -# gcc-base.conf, to make sure the change goes in the right place. -# -# To verify that your change has the desired effect on the final configuration -# you can use the manual test in tests/manual/mkspecs. -# - -include(g++.conf) - -QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_DWARF2 -QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_DWARF2 -QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += -g $$QMAKE_CFLAGS_DWARF2 - -QMAKE_LFLAGS_STATIC_LIB += -all_load - -QMAKE_CFLAGS_X86_64 += -Xarch_x86_64 -mmacosx-version-min=10.5 -QMAKE_CFLAGS_PPC_64 += -Xarch_ppc64 -mmacosx-version-min=10.5 - -QMAKE_CXXFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 -QMAKE_CXXFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 -QMAKE_OBJECTIVE_CFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 -QMAKE_OBJECTIVE_CFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 -QMAKE_LFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 -QMAKE_LFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 - -QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE -QMAKE_OBJCXXFLAGS_PRECOMPILE = -x objective-c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_OBJCXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE diff --git a/mkspecs/common/g++-macx.conf b/mkspecs/common/g++-macx.conf new file mode 100644 index 0000000..2251157 --- /dev/null +++ b/mkspecs/common/g++-macx.conf @@ -0,0 +1,32 @@ +# +# Qmake configuration for the GNU C++ compiler on Mac OS X +# +# Before making changes to this file, please read the comment in +# gcc-base.conf, to make sure the change goes in the right place. +# +# To verify that your change has the desired effect on the final configuration +# you can use the manual test in tests/manual/mkspecs. +# + +include(g++-base.conf) + +QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_DWARF2 +QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_DWARF2 +QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += -g $$QMAKE_CFLAGS_DWARF2 + +QMAKE_LFLAGS_STATIC_LIB += -all_load + +QMAKE_CFLAGS_X86_64 += -Xarch_x86_64 -mmacosx-version-min=10.5 +QMAKE_CFLAGS_PPC_64 += -Xarch_ppc64 -mmacosx-version-min=10.5 + +QMAKE_CXXFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 +QMAKE_CXXFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 +QMAKE_OBJECTIVE_CFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 +QMAKE_OBJECTIVE_CFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 +QMAKE_LFLAGS_X86_64 = $$QMAKE_CFLAGS_X86_64 +QMAKE_LFLAGS_PPC_64 = $$QMAKE_CFLAGS_PPC_64 + +QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} +QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE +QMAKE_OBJCXXFLAGS_PRECOMPILE = -x objective-c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} +QMAKE_OBJCXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE diff --git a/mkspecs/common/g++-unix.conf b/mkspecs/common/g++-unix.conf index 09b3e90..96e301e 100644 --- a/mkspecs/common/g++-unix.conf +++ b/mkspecs/common/g++-unix.conf @@ -8,7 +8,7 @@ # you can use the manual test in tests/manual/mkspecs. # -include(g++.conf) +include(g++-base.conf) QMAKE_LFLAGS_RELEASE += -Wl,-O1 QMAKE_LFLAGS_NOUNDEF += -Wl,--no-undefined diff --git a/mkspecs/common/g++.conf b/mkspecs/common/g++.conf index d73b38f..0ca4fbd 100644 --- a/mkspecs/common/g++.conf +++ b/mkspecs/common/g++.conf @@ -1,23 +1,11 @@ # -# Qmake configuration for the GNU C++ compiler +# Notice: g++.conf has been split into g++-base.conf and g++-unix.conf # -# Before making changes to this file, please read the comment in -# gcc-base.conf, to make sure the change goes in the right place. +# This file will make sure that anyone who's still including g++.conf +# directly will get a warning and an explanation of how to fix their mkspec # -# To verify that your change has the desired effect on the final configuration -# you can use the manual test in tests/manual/mkspecs. -# - -QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -g - -QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO - -QMAKE_LINK_C = $$QMAKE_CC -QMAKE_LINK_C_SHLIB = $$QMAKE_CC -QMAKE_PCH_OUTPUT_EXT = .gch +warning($$escape_expand("Your mkspec is including 'common/g++.conf', but the mkspecs have been refactored\\n\\tTo fix this include 'common/gcc-base-$${TARGET_PLATFORM}.conf and 'common/g++-$${TARGET_PLATFORM}.conf' instead")) -QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE} -QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE +# We include g++-unix.conf to keep the behavior of the old g++.conf +include(g++-unix.conf) \ No newline at end of file diff --git a/mkspecs/common/gcc-base-mac.conf b/mkspecs/common/gcc-base-mac.conf deleted file mode 100644 index 5c9a8a1..0000000 --- a/mkspecs/common/gcc-base-mac.conf +++ /dev/null @@ -1,43 +0,0 @@ -# -# Base qmake configuration for GCC on Mac OS X -# -# Before making changes to this file, please read the comment in -# gcc-base.conf, to make sure the change goes in the right place. -# -# To verify that your change has the desired effect on the final configuration -# you can use the manual test in tests/manual/mkspecs. -# - -include(gcc-base.conf) - -QMAKE_COMPILER_DEFINES += __APPLE__ __GNUC__ - -QMAKE_CFLAGS_X86 += -arch i386 -QMAKE_CFLAGS_X86_64 += -arch x86_64 -QMAKE_CFLAGS_PPC += -arch ppc -QMAKE_CFLAGS_PPC_64 += -arch ppc64 -QMAKE_CFLAGS_DWARF2 += -gdwarf-2 - -QMAKE_CXXFLAGS_X86 += $$QMAKE_CFLAGS_X86 -QMAKE_CXXFLAGS_X86_64 += $$QMAKE_CFLAGS_X86_64 -QMAKE_CXXFLAGS_PPC += $$QMAKE_CFLAGS_PPC -QMAKE_CXXFLAGS_PPC_64 += $$QMAKE_CFLAGS_PPC_64 -QMAKE_CXXFLAGS_DWARF2 += $$QMAKE_CFLAGS_DWARF2 - -QMAKE_OBJECTIVE_CFLAGS_X86 += $$QMAKE_CFLAGS_X86 -QMAKE_OBJECTIVE_CFLAGS_X86_64 += $$QMAKE_CFLAGS_X86_64 -QMAKE_OBJECTIVE_CFLAGS_PPC += $$QMAKE_CFLAGS_PPC -QMAKE_OBJECTIVE_CFLAGS_PPC_64 += $$QMAKE_CFLAGS_PPC_64 - -QMAKE_LFLAGS_X86 += $$QMAKE_CFLAGS_X86 -QMAKE_LFLAGS_X86_64 += $$QMAKE_CFLAGS_X86_64 -QMAKE_LFLAGS_PPC += $$QMAKE_CFLAGS_PPC -QMAKE_LFLAGS_PPC_64 += $$QMAKE_CFLAGS_PPC_64 - -QMAKE_LFLAGS += -headerpad_max_install_names -QMAKE_LFLAGS_SHLIB += -single_module -dynamiclib -QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB -QMAKE_LFLAGS_INCREMENTAL += -undefined suppress -flat_namespace -QMAKE_LFLAGS_SONAME += -install_name$${LITERAL_WHITESPACE} -QMAKE_LFLAGS_VERSION += -current_version$${LITERAL_WHITESPACE} -QMAKE_LFLAGS_COMPAT_VERSION += -compatibility_version$${LITERAL_WHITESPACE} diff --git a/mkspecs/common/gcc-base-macx.conf b/mkspecs/common/gcc-base-macx.conf new file mode 100644 index 0000000..5c9a8a1 --- /dev/null +++ b/mkspecs/common/gcc-base-macx.conf @@ -0,0 +1,43 @@ +# +# Base qmake configuration for GCC on Mac OS X +# +# Before making changes to this file, please read the comment in +# gcc-base.conf, to make sure the change goes in the right place. +# +# To verify that your change has the desired effect on the final configuration +# you can use the manual test in tests/manual/mkspecs. +# + +include(gcc-base.conf) + +QMAKE_COMPILER_DEFINES += __APPLE__ __GNUC__ + +QMAKE_CFLAGS_X86 += -arch i386 +QMAKE_CFLAGS_X86_64 += -arch x86_64 +QMAKE_CFLAGS_PPC += -arch ppc +QMAKE_CFLAGS_PPC_64 += -arch ppc64 +QMAKE_CFLAGS_DWARF2 += -gdwarf-2 + +QMAKE_CXXFLAGS_X86 += $$QMAKE_CFLAGS_X86 +QMAKE_CXXFLAGS_X86_64 += $$QMAKE_CFLAGS_X86_64 +QMAKE_CXXFLAGS_PPC += $$QMAKE_CFLAGS_PPC +QMAKE_CXXFLAGS_PPC_64 += $$QMAKE_CFLAGS_PPC_64 +QMAKE_CXXFLAGS_DWARF2 += $$QMAKE_CFLAGS_DWARF2 + +QMAKE_OBJECTIVE_CFLAGS_X86 += $$QMAKE_CFLAGS_X86 +QMAKE_OBJECTIVE_CFLAGS_X86_64 += $$QMAKE_CFLAGS_X86_64 +QMAKE_OBJECTIVE_CFLAGS_PPC += $$QMAKE_CFLAGS_PPC +QMAKE_OBJECTIVE_CFLAGS_PPC_64 += $$QMAKE_CFLAGS_PPC_64 + +QMAKE_LFLAGS_X86 += $$QMAKE_CFLAGS_X86 +QMAKE_LFLAGS_X86_64 += $$QMAKE_CFLAGS_X86_64 +QMAKE_LFLAGS_PPC += $$QMAKE_CFLAGS_PPC +QMAKE_LFLAGS_PPC_64 += $$QMAKE_CFLAGS_PPC_64 + +QMAKE_LFLAGS += -headerpad_max_install_names +QMAKE_LFLAGS_SHLIB += -single_module -dynamiclib +QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB +QMAKE_LFLAGS_INCREMENTAL += -undefined suppress -flat_namespace +QMAKE_LFLAGS_SONAME += -install_name$${LITERAL_WHITESPACE} +QMAKE_LFLAGS_VERSION += -current_version$${LITERAL_WHITESPACE} +QMAKE_LFLAGS_COMPAT_VERSION += -compatibility_version$${LITERAL_WHITESPACE} diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index 41280c6..2d8a02f 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -7,21 +7,21 @@ # # Platform-specific options shared by these compilers are put into: # -# - gcc-base-mac.conf +# - gcc-base-macx.conf # - gcc-base-unix.conf # # These base files are then combined with configurations for each compiler: # -# - g++.conf -# - g++-mac.conf +# - g++-base.conf +# - g++-macx.conf # - g++-unix.conf # - llvm.conf # - clang.conf # # The combination happens in the top level mkspec, by including a platform- -# specific version of the base-file, for example gcc-base-mac.conf, and then +# specific version of the base-file, for example gcc-base-macx.conf, and then # a (possibly platform-specific) version of the actual compiler configuration, -# for example g++-mac.conf. +# for example g++-macx.conf. # # If you are making changes to any of these files, please consider the # possible effect it may have due to these include-rules, and whether it diff --git a/mkspecs/macx-g++/qmake.conf b/mkspecs/macx-g++/qmake.conf index fd36b70..0fd2c74 100644 --- a/mkspecs/macx-g++/qmake.conf +++ b/mkspecs/macx-g++/qmake.conf @@ -17,6 +17,6 @@ QMAKE_CC = gcc QMAKE_CXX = g++ include(../common/mac.conf) -include(../common/gcc-base-mac.conf) -include(../common/g++-mac.conf) +include(../common/gcc-base-macx.conf) +include(../common/g++-macx.conf) load(qt_config) diff --git a/mkspecs/macx-g++40/qmake.conf b/mkspecs/macx-g++40/qmake.conf index cfdd724..aa10fa2 100644 --- a/mkspecs/macx-g++40/qmake.conf +++ b/mkspecs/macx-g++40/qmake.conf @@ -17,7 +17,7 @@ QMAKE_CC = gcc-4.0 QMAKE_CXX = g++-4.0 include(../common/mac.conf) -include(../common/gcc-base-mac.conf) -include(../common/g++-mac.conf) +include(../common/gcc-base-macx.conf) +include(../common/g++-macx.conf) load(qt_config) diff --git a/mkspecs/macx-g++42/qmake.conf b/mkspecs/macx-g++42/qmake.conf index 08305ba..b2be5ed 100644 --- a/mkspecs/macx-g++42/qmake.conf +++ b/mkspecs/macx-g++42/qmake.conf @@ -17,7 +17,7 @@ QMAKE_CC = gcc-4.2 QMAKE_CXX = g++-4.2 include(../common/mac.conf) -include(../common/gcc-base-mac.conf) -include(../common/g++-mac.conf) +include(../common/gcc-base-macx.conf) +include(../common/g++-macx.conf) load(qt_config) diff --git a/mkspecs/macx-llvm/qmake.conf b/mkspecs/macx-llvm/qmake.conf index 95c2b28..94f9688 100644 --- a/mkspecs/macx-llvm/qmake.conf +++ b/mkspecs/macx-llvm/qmake.conf @@ -15,7 +15,7 @@ QMAKE_INCREMENTAL_STYLE = sublib include(../common/mac.conf) include(../common/llvm.conf) -include(../common/gcc-base-mac.conf) +include(../common/gcc-base-macx.conf) QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE diff --git a/mkspecs/macx-xcode/qmake.conf b/mkspecs/macx-xcode/qmake.conf index dc79b3d..4cb4626 100755 --- a/mkspecs/macx-xcode/qmake.conf +++ b/mkspecs/macx-xcode/qmake.conf @@ -10,8 +10,8 @@ CONFIG += qt warn_on release lib_version_first incremental plugin_no_soname li QT += core gui include(../common/mac.conf) -include(../common/gcc-base-mac.conf) -include(../common/g++-mac.conf) +include(../common/gcc-base-macx.conf) +include(../common/g++-macx.conf) QMAKE_CC = QMAKE_CXX = diff --git a/mkspecs/symbian-gcce/qmake.conf b/mkspecs/symbian-gcce/qmake.conf index f012217..7051a9c 100644 --- a/mkspecs/symbian-gcce/qmake.conf +++ b/mkspecs/symbian-gcce/qmake.conf @@ -4,7 +4,8 @@ include(../common/symbian/symbian-makefile.conf) -include(../common/g++.conf) +include(../common/g++-unix.conf) +include(../common/gcc-base-unix.conf) QMAKE_CC = arm-none-symbianelf-gcc QMAKE_CXX = arm-none-symbianelf-g++ diff --git a/mkspecs/unsupported/macx-clang/qmake.conf b/mkspecs/unsupported/macx-clang/qmake.conf index 17892e8..aaabf27 100644 --- a/mkspecs/unsupported/macx-clang/qmake.conf +++ b/mkspecs/unsupported/macx-clang/qmake.conf @@ -11,7 +11,7 @@ QMAKE_INCREMENTAL_STYLE = sublib include(../../common/mac.conf) include(../../common/clang.conf) -include(../../common/gcc-base-mac.conf) +include(../../common/gcc-base-macx.conf) QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE diff --git a/mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf b/mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf index 26de9b7..bb760b2 100644 --- a/mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf +++ b/mkspecs/unsupported/qws/qnx-generic-g++/qmake.conf @@ -61,7 +61,6 @@ QMAKE_PCH_OUTPUT_EXT = .gch QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions QMAKE_LFLAGS_DYNAMIC_LIST = -Wl,--dynamic-list, -#include(../../common/g++.conf) include(../../common/unix.conf) QMAKE_CFLAGS_THREAD = -D_REENTRANT -- cgit v0.12 From 63c068434c53c705aa61217b4cbd006bf4f49b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 27 Oct 2010 13:58:57 +0200 Subject: Don't put Objective-C sources in SOURCES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alexis Ménard --- src/plugins/bearer/corewlan/corewlan.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/bearer/corewlan/corewlan.pro b/src/plugins/bearer/corewlan/corewlan.pro index 922a501..22ad550 100644 --- a/src/plugins/bearer/corewlan/corewlan.pro +++ b/src/plugins/bearer/corewlan/corewlan.pro @@ -16,9 +16,10 @@ HEADERS += qcorewlanengine.h \ ../qbearerengine_impl.h SOURCES += main.cpp \ - qcorewlanengine.mm \ ../qnetworksession_impl.cpp +OBJECTIVE_SOURCES += qcorewlanengine.mm + QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer target.path += $$[QT_INSTALL_PLUGINS]/bearer INSTALLS += target -- cgit v0.12 From afc70e04f5ca8b1fc330c05547f7923362686577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 27 Oct 2010 16:18:28 +0200 Subject: Move list of trusted benchmarks out of QA dungeon and into Qt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To run the list of trusted benchmark do 'make check-trusted' in either the root benchmarks directory or for any of the immediate sub-targets. Normal 'make check' environment variables apply, such as TESTRUNNER and TESTARGS. Reviewed-by: João Abecasis --- tests/benchmarks/benchmarks.pro | 3 +++ tests/benchmarks/corelib/corelib.pro | 10 +++++++++- tests/benchmarks/declarative/declarative.pro | 2 +- tests/benchmarks/gui/gui.pro | 7 +++++++ tests/benchmarks/network/network.pro | 7 +++++++ tests/benchmarks/opengl/opengl.pro | 2 ++ tests/benchmarks/script/script.pro | 7 +++++++ tests/benchmarks/svg/svg.pro | 2 ++ tests/benchmarks/trusted-benchmarks.pri | 8 ++++++++ 9 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 tests/benchmarks/trusted-benchmarks.pri diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro index 01d5cd5..00a1b37 100644 --- a/tests/benchmarks/benchmarks.pro +++ b/tests/benchmarks/benchmarks.pro @@ -7,3 +7,6 @@ SUBDIRS = \ svg contains(QT_CONFIG, opengl): SUBDIRS += opengl contains(QT_CONFIG, declarative): SUBDIRS += declarative + +check-trusted.CONFIG += recursive +QMAKE_EXTRA_TARGETS += check-trusted diff --git a/tests/benchmarks/corelib/corelib.pro b/tests/benchmarks/corelib/corelib.pro index 8a6941b..335280e 100644 --- a/tests/benchmarks/corelib/corelib.pro +++ b/tests/benchmarks/corelib/corelib.pro @@ -4,5 +4,13 @@ SUBDIRS = \ kernel \ thread \ tools \ - codecs \ + codecs \ plugin + +TRUSTED_BENCHMARKS += \ + kernel/qmetaobject \ + kernel/qmetatype \ + kernel/qobject \ + thread/qthreadstorage + +include(../trusted-benchmarks.pri) \ No newline at end of file diff --git a/tests/benchmarks/declarative/declarative.pro b/tests/benchmarks/declarative/declarative.pro index 5dd31f3..cb02a35 100644 --- a/tests/benchmarks/declarative/declarative.pro +++ b/tests/benchmarks/declarative/declarative.pro @@ -12,4 +12,4 @@ SUBDIRS += \ contains(QT_CONFIG, opengl): SUBDIRS += painting - +include(../trusted-benchmarks.pri) diff --git a/tests/benchmarks/gui/gui.pro b/tests/benchmarks/gui/gui.pro index 946f184..d825458 100644 --- a/tests/benchmarks/gui/gui.pro +++ b/tests/benchmarks/gui/gui.pro @@ -9,3 +9,10 @@ SUBDIRS = \ painting \ styles \ text + +TRUSTED_BENCHMARKS += \ + graphicsview/functional/GraphicsViewBenchmark \ + graphicsview/qgraphicsview \ + painting/qtracebench + +include(../trusted-benchmarks.pri) \ No newline at end of file diff --git a/tests/benchmarks/network/network.pro b/tests/benchmarks/network/network.pro index 73de556..692a0a1 100644 --- a/tests/benchmarks/network/network.pro +++ b/tests/benchmarks/network/network.pro @@ -4,3 +4,10 @@ SUBDIRS = \ kernel \ ssl \ socket + +TRUSTED_BENCHMARKS += \ + kernel/qhostinfo \ + socket/qtcpserver \ + ssl/qsslsocket + +include(../trusted-benchmarks.pri) \ No newline at end of file diff --git a/tests/benchmarks/opengl/opengl.pro b/tests/benchmarks/opengl/opengl.pro index 5c58751..b510c2b 100644 --- a/tests/benchmarks/opengl/opengl.pro +++ b/tests/benchmarks/opengl/opengl.pro @@ -8,3 +8,5 @@ QT += opengl # Input SOURCES += main.cpp + +include(../trusted-benchmarks.pri) \ No newline at end of file diff --git a/tests/benchmarks/script/script.pro b/tests/benchmarks/script/script.pro index 8d689b6..34910f7 100644 --- a/tests/benchmarks/script/script.pro +++ b/tests/benchmarks/script/script.pro @@ -3,3 +3,10 @@ SUBDIRS = \ qscriptclass \ qscriptengine \ qscriptvalue + +TRUSTED_BENCHMARKS += \ + qscriptclass \ + qscriptvalue \ + qscriptengine + +include(../trusted-benchmarks.pri) \ No newline at end of file diff --git a/tests/benchmarks/svg/svg.pro b/tests/benchmarks/svg/svg.pro index cdc2ca5..d84eb71 100644 --- a/tests/benchmarks/svg/svg.pro +++ b/tests/benchmarks/svg/svg.pro @@ -1,3 +1,5 @@ TEMPLATE = subdirs SUBDIRS = \ qsvgrenderer + +include(../trusted-benchmarks.pri) \ No newline at end of file diff --git a/tests/benchmarks/trusted-benchmarks.pri b/tests/benchmarks/trusted-benchmarks.pri new file mode 100644 index 0000000..632dcff --- /dev/null +++ b/tests/benchmarks/trusted-benchmarks.pri @@ -0,0 +1,8 @@ +# Edit the list of trusted benchmarks in each of the sub-targets + +check-trusted.depends = qmake +for(benchmark, TRUSTED_BENCHMARKS) { + check-trusted.commands += (cd $$benchmark && $(MAKE) -f $(MAKEFILE) check); +} + +QMAKE_EXTRA_TARGETS += check-trusted -- cgit v0.12 From b36e845dde90313cf98df118ce6ffd88502b943b Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 28 Oct 2010 11:51:45 +0200 Subject: samegame: white space Reviewed-by: Kai Koehne --- .../declarative/samegame/SamegameCore/samegame.js | 198 +++++++++++---------- 1 file changed, 108 insertions(+), 90 deletions(-) diff --git a/demos/declarative/samegame/SamegameCore/samegame.js b/demos/declarative/samegame/SamegameCore/samegame.js index 9266767..e618a10 100755 --- a/demos/declarative/samegame/SamegameCore/samegame.js +++ b/demos/declarative/samegame/SamegameCore/samegame.js @@ -9,12 +9,14 @@ var scoresURL = ""; var gameDuration; var component = Qt.createComponent(blockSrc); -//Index function used instead of a 2D array -function index(column,row) { - return column + (row * maxColumn); +// Index function used instead of a 2D array +function index(column, row) +{ + return column + row * maxColumn; } -function timeStr(msecs) { +function timeStr(msecs) +{ var secs = Math.floor(msecs/1000); var m = Math.floor(secs/60); var ret = "" + m + "m " + (secs%60) + "s"; @@ -23,47 +25,48 @@ function timeStr(msecs) { function startNewGame() { - //Delete blocks from previous game - for(var i = 0; i= maxColumn || column < 0 || row >= maxRow || row < 0) + if (column >= maxColumn || column < 0 || row >= maxRow || row < 0) return; - if(board[index(column, row)] == null) + if (board[index(column, row)] == null) return; - //If it's a valid block, remove it and all connected (does nothing if it's not connected) + // If it's a valid block, remove it and all connected (does nothing if it's not connected) floodFill(column,row, -1); - if(fillFound <= 0) + if (fillFound <= 0) return; gameCanvas.score += (fillFound - 1) * (fillFound - 1); shuffleDown(); @@ -72,65 +75,65 @@ function handleClick(x,y) function floodFill(column,row,type) { - if(board[index(column, row)] == null) + if (board[index(column, row)] == null) return; var first = false; - if(type == -1){ + if (type == -1) { first = true; type = board[index(column,row)].type; - - //Flood fill initialization + + // Flood fill initialization fillFound = 0; floodBoard = new Array(maxIndex); } - if(column >= maxColumn || column < 0 || row >= maxRow || row < 0) + if (column >= maxColumn || column < 0 || row >= maxRow || row < 0) return; - if(floodBoard[index(column, row)] == 1 || (!first && type != board[index(column,row)].type)) + if (floodBoard[index(column, row)] == 1 || (!first && type != board[index(column, row)].type)) return; floodBoard[index(column, row)] = 1; - floodFill(column+1,row,type); - floodFill(column-1,row,type); - floodFill(column,row+1,type); - floodFill(column,row-1,type); - if(first==true && fillFound == 0) - return;//Can't remove single blocks - board[index(column,row)].dying = true; - board[index(column,row)] = null; + floodFill(column + 1, row, type); + floodFill(column - 1, row, type); + floodFill(column, row + 1, type); + floodFill(column, row - 1, type); + if (first == true && fillFound == 0) + return; // Can't remove single blocks + board[index(column, row)].dying = true; + board[index(column, row)] = null; fillFound += 1; } function shuffleDown() { - //Fall down - for(var column=0; column=0; row--){ - if(board[index(column,row)] == null){ + for (var row = maxRow - 1; row >= 0; row--) { + if (board[index(column,row)] == null) { fallDist += 1; - }else{ - if(fallDist > 0){ - var obj = board[index(column,row)]; - obj.y = (row+fallDist) * gameCanvas.blockSize; - board[index(column,row+fallDist)] = obj; - board[index(column,row)] = null; + } else { + if (fallDist > 0) { + var obj = board[index(column, row)]; + obj.y = (row + fallDist) * gameCanvas.blockSize; + board[index(column, row + fallDist)] = obj; + board[index(column, row)] = null; } } } } - //Fall to the left + // Fall to the left fallDist = 0; - for(column=0; column 0){ - for(row=0; row 0) { + for (row = 0; row < maxRow; row++) { + obj = board[index(column, row)]; + if (obj == null) continue; - obj.x = (column-fallDist) * gameCanvas.blockSize; - board[index(column-fallDist,row)] = obj; - board[index(column,row)] = null; + obj.x = (column - fallDist) * gameCanvas.blockSize; + board[index(column - fallDist,row)] = obj; + board[index(column, row)] = null; } } } @@ -139,58 +142,59 @@ function shuffleDown() function victoryCheck() { - //awards bonuses for no blocks left + // Awards bonuses for no blocks left var deservesBonus = true; - for(var column=maxColumn-1; column>=0; column--) - if(board[index(column, maxRow - 1)] != null) + for (var column = maxColumn - 1; column >= 0; column--) + if (board[index(column, maxRow - 1)] != null) deservesBonus = false; - if(deservesBonus) + if (deservesBonus) gameCanvas.score += 500; - //Checks for game over - if(deservesBonus || !(floodMoveCheck(0,maxRow-1, -1))){ + // Checks for game over + if (deservesBonus || !(floodMoveCheck(0, maxRow - 1, -1))) { gameDuration = new Date() - gameDuration; nameInputDialog.show("You won! Please enter your name: "); nameInputDialog.initialWidth = nameInputDialog.text.width + 20; - if(nameInputDialog.name == "") + if (nameInputDialog.name == "") nameInputDialog.width = nameInputDialog.initialWidth; - nameInputDialog.text.opacity = 0;//Just a spacer + nameInputDialog.text.opacity = 0; // Just a spacer } } -//only floods up and right, to see if it can find adjacent same-typed blocks +// Only floods up and right, to see if it can find adjacent same-typed blocks function floodMoveCheck(column, row, type) { - if(column >= maxColumn || column < 0 || row >= maxRow || row < 0) + if (column >= maxColumn || column < 0 || row >= maxRow || row < 0) return false; - if(board[index(column, row)] == null) + if (board[index(column, row)] == null) return false; var myType = board[index(column, row)].type; - if(type == myType) + if (type == myType) return true; return floodMoveCheck(column + 1, row, myType) || - floodMoveCheck(column, row - 1, board[index(column,row)].type); + floodMoveCheck(column, row - 1, board[index(column, row)].type); } -function createBlock(column,row){ +function createBlock(column,row) +{ // Note that we don't wait for the component to become ready. This will // only work if the block QML is a local file. Otherwise the component will // not be ready immediately. There is a statusChanged signal on the // component you could use if you want to wait to load remote files. - if(component.status == Component.Ready){ + if (component.status == Component.Ready) { var dynamicObject = component.createObject(gameCanvas); - if(dynamicObject == null){ + if (dynamicObject == null) { console.log("error creating block"); console.log(component.errorString()); return false; } dynamicObject.type = Math.floor(Math.random() * 3); - dynamicObject.x = column*gameCanvas.blockSize; - dynamicObject.y = row*gameCanvas.blockSize; + dynamicObject.x = column * gameCanvas.blockSize; + dynamicObject.y = row * gameCanvas.blockSize; dynamicObject.width = gameCanvas.blockSize; dynamicObject.height = gameCanvas.blockSize; dynamicObject.spawned = true; - board[index(column,row)] = dynamicObject; - }else{ + board[index(column, row)] = dynamicObject; + } else { console.log("error loading block component"); console.log(component.errorString()); return false; @@ -198,23 +202,35 @@ function createBlock(column,row){ return true; } -function saveHighScore(name) { - if(scoresURL!="") +function saveHighScore(name) +{ + if (scoresURL != "") sendHighScore(name); - //OfflineStorage - var db = openDatabaseSync("SameGameScores", "1.0", "Local SameGame High Scores",100); + // Offline storage + var db = openDatabaseSync( + "SameGameScores", + "1.0", + "Local SameGame High Scores", + 100 + ); var dataStr = "INSERT INTO Scores VALUES(?, ?, ?, ?)"; - var data = [name, gameCanvas.score, maxColumn+"x"+maxRow ,Math.floor(gameDuration/1000)]; + var data = [ + name, + gameCanvas.score, + maxColumn + "x" + maxRow, + Math.floor(gameDuration / 1000) + ]; db.transaction( function(tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(name TEXT, score NUMBER, gridSize TEXT, time NUMBER)'); tx.executeSql(dataStr, data); - //Only show results for the current grid size - var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "'+maxColumn+"x"+maxRow+'" ORDER BY score desc LIMIT 10'); + // Only show results for the current grid size + var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "' + + maxColumn + "x" + maxRow + '" ORDER BY score desc LIMIT 10'); var r = "\nHIGH SCORES for this grid size\n\n" - for(var i = 0; i < rs.rows.length; i++){ - r += (i+1)+". " + rs.rows.item(i).name +' got ' + for (var i = 0; i < rs.rows.length; i++) { + r += (i+1) + ". " + rs.rows.item(i).name + ' got ' + rs.rows.item(i).score + ' points in ' + rs.rows.item(i).time + ' seconds.\n'; } @@ -223,13 +239,15 @@ function saveHighScore(name) { ); } -function sendHighScore(name) { +function sendHighScore(name) +{ var postman = new XMLHttpRequest() - var postData = "name="+name+"&score="+gameCanvas.score - +"&gridSize="+maxColumn+"x"+maxRow +"&time="+Math.floor(gameDuration/1000); + var postData = "name=" + name + "&score=" + gameCanvas.score + + "&gridSize=" + maxColumn + "x" + maxRow + + "&time=" + Math.floor(gameDuration / 1000); postman.open("POST", scoresURL, true); postman.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - postman.onreadystatechange = function() { + postman.onreadystatechange = function() { if (postman.readyState == postman.DONE) { dialog.show("Your score has been uploaded."); } -- cgit v0.12 From 0c643b179c5154c50b61dba421016b7b48794720 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 29 Oct 2010 15:04:46 +0200 Subject: Simplify object lifetime management when moving objects to a QThread The documentation for Qt::AutoConnection states is a signal is emitted from the same thread as the receiving object, the connection should behave as Qt::DirectConnection. The actual behavior prior to this commit was different from the documentation; if the signal was emitted in a thread different from the sender's thread, then we would queue (which is now corrected). By making the behavior match the documentation, it is now possible to connect QThread's finished() signal to an object's deleteLater() slot and the slot will execute when finished() is emitted (previously it was queued). QObject::deleteLater() uses a posted QEvent::DeferredDelete event to trigger deletion of the object. In QThread, after emitting the finished() signal, we now send all pending DeferredDelete events to ensure that all pending deletions happen. We have precedence for this behavior, QCoreApplication::exec() does the same thing after emitting the aboutToQuit() signal. Reviewed-by: joao Reviewed-by: olivier --- src/corelib/kernel/qobject.cpp | 4 +- src/corelib/thread/qthread_unix.cpp | 1 + src/corelib/thread/qthread_win.cpp | 1 + tests/auto/qobject/tst_qobject.cpp | 78 +++++++++++++++++++++++++++++++++++++ tests/auto/qthread/tst_qthread.cpp | 14 +++++++ 5 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 573bb50..7fe9c52 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3508,9 +3508,7 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign // determine if this connection should be sent immediately or // put into the event queue - if ((c->connectionType == Qt::AutoConnection - && (!receiverInSameThread - || receiver->d_func()->threadData != sender->d_func()->threadData)) + if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread) || (c->connectionType == Qt::QueuedConnection)) { queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv); continue; diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index a44a0e8..e39e577 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -343,6 +343,7 @@ void QThreadPrivate::finish(void *arg) emit thr->terminated(); d->terminated = false; emit thr->finished(); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); if (d->data->eventDispatcher) { d->data->eventDispatcher->closingDown(); diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index f0cbe8d..4a967ed 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -332,6 +332,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) emit thr->terminated(); d->terminated = false; emit thr->finished(); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); if (d->data->eventDispatcher) { d->data->eventDispatcher->closingDown(); diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 24cd5a3..a09f109 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -134,6 +134,7 @@ private slots: void connectConstructorByMetaMethod(); void disconnectByMetaMethod(); void disconnectNotSignalMetaMethod(); + void autoConnectionBehavior(); protected: }; @@ -3847,5 +3848,82 @@ void tst_QObject::disconnectNotSignalMetaMethod() QVERIFY(!QObject::disconnect(&s, slot, &r, QMetaMethod())); } +class ThreadAffinityThread : public QThread +{ +public: + SenderObject *sender; + + ThreadAffinityThread(SenderObject *sender) + : sender(sender) + { } + void run() + { + sender->emitSignal1(); + } +}; + +void tst_QObject::autoConnectionBehavior() +{ + SenderObject *sender = new SenderObject; + ReceiverObject *receiver = new ReceiverObject; + connect(sender, SIGNAL(signal1()), receiver, SLOT(slot1())); + + // at emit, currentThread == sender->thread(), currentThread == receiver->thread(), sender->thread() == receiver->thread() + QVERIFY(!receiver->called(1)); + sender->emitSignal1(); + QVERIFY(receiver->called(1)); + receiver->reset(); + + // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() == receiver->thread() + ThreadAffinityThread emitThread1(sender); + QVERIFY(!receiver->called(1)); + emitThread1.start(); + QVERIFY(emitThread1.wait(30000)); + QVERIFY(!receiver->called(1)); + QCoreApplication::sendPostedEvents(receiver, QEvent::MetaCall); + QVERIFY(receiver->called(1)); + receiver->reset(); + + // at emit, currentThread == sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread() + sender->moveToThread(&emitThread1); + QVERIFY(!receiver->called(1)); + emitThread1.start(); + QVERIFY(emitThread1.wait(30000)); + QVERIFY(!receiver->called(1)); + QCoreApplication::sendPostedEvents(receiver, QEvent::MetaCall); + QVERIFY(receiver->called(1)); + receiver->reset(); + + // at emit, currentThread != sender->thread(), currentThread == receiver->thread(), sender->thread() != receiver->thread() + QVERIFY(!receiver->called(1)); + sender->emitSignal1(); + QVERIFY(receiver->called(1)); + receiver->reset(); + + // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread() + ThreadAffinityThread emitThread2(sender); + QThread receiverThread; + QTimer *timer = new QTimer; + timer->setSingleShot(true); + timer->setInterval(100); + connect(&receiverThread, SIGNAL(started()), timer, SLOT(start())); + connect(timer, SIGNAL(timeout()), &receiverThread, SLOT(quit()), Qt::DirectConnection); + connect(&receiverThread, SIGNAL(finished()), timer, SLOT(deleteLater())); + timer->moveToThread(&receiverThread); + + receiver->moveToThread(&receiverThread); + QVERIFY(!receiver->called(1)); + emitThread2.start(); + QVERIFY(emitThread2.wait(30000)); + QVERIFY(!receiver->called(1)); + receiverThread.start(); + QVERIFY(receiverThread.wait(30000)); + QVERIFY(receiver->called(1)); + receiver->reset(); + + delete sender; + delete receiver; +} + QTEST_MAIN(tst_QObject) #include "tst_qobject.moc" diff --git a/tests/auto/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp index 843749a..f290a2b 100644 --- a/tests/auto/qthread/tst_qthread.cpp +++ b/tests/auto/qthread/tst_qthread.cpp @@ -106,6 +106,7 @@ private slots: void adoptMultipleThreads(); void QTBUG13810_exitAndStart(); + void connectThreadFinishedSignalToObjectDeleteLaterSlot(); void stressTest(); }; @@ -975,6 +976,19 @@ void tst_QThread::QTBUG13810_exitAndStart() QCOMPARE(sync1.m_prop, 89); } +void tst_QThread::connectThreadFinishedSignalToObjectDeleteLaterSlot() +{ + QThread thread; + QObject *object = new QObject; + QWeakPointer p = object; + QVERIFY(!p.isNull()); + connect(&thread, SIGNAL(started()), &thread, SLOT(quit()), Qt::DirectConnection); + connect(&thread, SIGNAL(finished()), object, SLOT(deleteLater())); + object->moveToThread(&thread); + thread.start(); + QVERIFY(thread.wait(30000)); + QVERIFY(p.isNull()); +} QTEST_MAIN(tst_QThread) #include "tst_qthread.moc" -- cgit v0.12 From bf8a9dc1248083dfb0ce5599b11af1727d349631 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 29 Oct 2010 15:03:38 +0200 Subject: Don't crash when null-pointer is passed to qScriptValueFromValue() qScriptValueFromValue_helper() (or rather, QScriptEnginePrivate::create()) will fall back to wrapping the value using newVariant(), so there is no reason for the QVariant specialization to check the return value. (In particular, if the return value was invalid, that's _because_ the engine was null, so we should definitely not call a function on the engine.) Task-number: QTBUG-14842 Reviewed-by: Jedrzej Nowacki --- src/script/api/qscriptengine.h | 5 +---- tests/auto/qscriptengine/tst_qscriptengine.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h index 830d477..24c8c13 100644 --- a/src/script/api/qscriptengine.h +++ b/src/script/api/qscriptengine.h @@ -332,10 +332,7 @@ inline QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &t) template <> inline QScriptValue qScriptValueFromValue(QScriptEngine *engine, const QVariant &v) { - QScriptValue result = qScriptValueFromValue_helper(engine, v.userType(), v.data()); - if (!result.isValid()) - result = engine->newVariant(v); - return result; + return qScriptValueFromValue_helper(engine, v.userType(), v.data()); } inline bool qscriptvalue_cast_helper(const QScriptValue &value, int type, void *ptr) diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 7133a6c..3a376ec 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -120,6 +120,7 @@ private slots: void uncaughtException(); void errorMessage_QT679(); void valueConversion(); + void qScriptValueFromValue_noEngine(); void importExtension(); void infiniteRecursion(); void castWithPrototypeChain(); @@ -2258,6 +2259,12 @@ void tst_QScriptEngine::valueConversion() } } +void tst_QScriptEngine::qScriptValueFromValue_noEngine() +{ + QVERIFY(!qScriptValueFromValue(0, 123).isValid()); + QVERIFY(!qScriptValueFromValue(0, QVariant(123)).isValid()); +} + static QScriptValue __import__(QScriptContext *ctx, QScriptEngine *eng) { return eng->importExtension(ctx->argument(0).toString()); -- cgit v0.12 From bd3c35cf1cbdbde16df9357a08b8b45a96fa3a5e Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 29 Oct 2010 15:15:45 +0200 Subject: Improve QtScript test coverage Based on BullsEye coverage reports. --- tests/auto/qscriptable/tst_qscriptable.cpp | 4 +- tests/auto/qscriptclass/tst_qscriptclass.cpp | 40 ++++++ tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 38 ++++++ tests/auto/qscriptengine/tst_qscriptengine.cpp | 141 +++++++++++++++++++-- .../qscriptextqobject/tst_qscriptextqobject.cpp | 100 +++++++++++++++ .../tst_qscriptvalueiterator.cpp | 21 +++ 6 files changed, 332 insertions(+), 12 deletions(-) diff --git a/tests/auto/qscriptable/tst_qscriptable.cpp b/tests/auto/qscriptable/tst_qscriptable.cpp index 3c781b1..86dd80e 100644 --- a/tests/auto/qscriptable/tst_qscriptable.cpp +++ b/tests/auto/qscriptable/tst_qscriptable.cpp @@ -131,7 +131,7 @@ QScriptValue MyScriptable::getArguments() int MyScriptable::getArgumentCount() { - return context()->argumentCount(); + return argumentCount(); } void MyScriptable::foo() @@ -283,6 +283,8 @@ void tst_QScriptable::engine() void tst_QScriptable::thisObject() { + QVERIFY(!m_scriptable.thisObject().isValid()); + m_engine.evaluate("o = { }"); { QScriptValue ret = m_engine.evaluate("o.__proto__ = scriptable;" diff --git a/tests/auto/qscriptclass/tst_qscriptclass.cpp b/tests/auto/qscriptclass/tst_qscriptclass.cpp index b4dbe73..2c669f3 100644 --- a/tests/auto/qscriptclass/tst_qscriptclass.cpp +++ b/tests/auto/qscriptclass/tst_qscriptclass.cpp @@ -68,6 +68,7 @@ private slots: void getAndSetProperty(); void enumerate(); void extension(); + void defaultImplementations(); }; tst_QScriptClass::tst_QScriptClass() @@ -603,6 +604,8 @@ void tst_QScriptClass::newInstance() QVERIFY(obj2.data().strictlyEquals(num)); QVERIFY(obj2.prototype().strictlyEquals(cls.prototype())); QCOMPARE(obj2.scriptClass(), (QScriptClass*)&cls); + QVERIFY(!obj2.equals(obj1)); + QVERIFY(!obj2.strictlyEquals(obj1)); QScriptValue obj3 = eng.newObject(); QCOMPARE(obj3.scriptClass(), (QScriptClass*)0); @@ -730,6 +733,14 @@ void tst_QScriptClass::getAndSetProperty() QCOMPARE(cls.lastPropertyId(), foo2Id); } + // attempt to delete custom property + obj1.setProperty(foo2, QScriptValue()); + // delete real property + obj1.setProperty(foo, QScriptValue()); + QVERIFY(!obj1.property(foo).isValid()); + obj1.setProperty(foo, num); + QVERIFY(obj1.property(foo).equals(num)); + // remove script class; normal properties should remain obj1.setScriptClass(0); QCOMPARE(obj1.scriptClass(), (QScriptClass*)0); @@ -805,6 +816,7 @@ void tst_QScriptClass::extension() QCOMPARE((int)cls.lastExtensionType(), -1); QVERIFY(!obj.instanceOf(obj)); QCOMPARE((int)cls.lastExtensionType(), -1); + QVERIFY(!obj.construct().isValid()); } // Callable { @@ -1017,5 +1029,33 @@ void tst_QScriptClass::extension() } } +void tst_QScriptClass::defaultImplementations() +{ + QScriptEngine eng; + + QScriptClass defaultClass(&eng); + QCOMPARE(defaultClass.engine(), &eng); + QVERIFY(!defaultClass.prototype().isValid()); + QCOMPARE(defaultClass.name(), QString()); + + QScriptValue obj = eng.newObject(&defaultClass); + QCOMPARE(obj.scriptClass(), &defaultClass); + + QScriptString name = eng.toStringHandle("foo"); + uint id = -1; + QCOMPARE(defaultClass.queryProperty(obj, name, QScriptClass::HandlesReadAccess, &id), QScriptClass::QueryFlags(0)); + QVERIFY(!defaultClass.property(obj, name, id).isValid()); + QCOMPARE(defaultClass.propertyFlags(obj, name, id), QScriptValue::PropertyFlags(0)); + defaultClass.setProperty(obj, name, id, 123); + QVERIFY(!obj.property(name).isValid()); + + QCOMPARE(defaultClass.newIterator(obj), (QScriptClassPropertyIterator*)0); + + QVERIFY(!defaultClass.supportsExtension(QScriptClass::Callable)); + QVERIFY(!defaultClass.supportsExtension(QScriptClass::HasInstance)); + QVERIFY(!defaultClass.extension(QScriptClass::Callable).isValid()); + QVERIFY(!defaultClass.extension(QScriptClass::HasInstance).isValid()); +} + QTEST_MAIN(tst_QScriptClass) #include "tst_qscriptclass.moc" diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index 617c183..99558eb 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -44,6 +44,7 @@ #include #include +#include //TESTED_CLASS= //TESTED_FILES= @@ -77,6 +78,7 @@ private slots: void scopeChain(); void pushAndPopScope(); void getSetActivationObject(); + void getSetActivationObject_customContext(); void inheritActivationAndThisObject(); void toString(); void calledAsConstructor(); @@ -513,8 +515,30 @@ void tst_QScriptContext::pushAndPopContext() QScriptContext *ctx3 = eng.pushContext(); ctx3->activationObject().setProperty("foo", QScriptValue(&eng, 123)); QVERIFY(eng.evaluate("foo").strictlyEquals(QScriptValue(&eng, 123))); + QCOMPARE(ctx3->activationObject().propertyFlags("foo"), QScriptValue::PropertyFlags(0)); + + ctx3->activationObject().setProperty(4, 456); + QVERIFY(ctx3->activationObject().property(4, QScriptValue::ResolveLocal).equals(456)); + eng.evaluate("var bar = 'ciao'"); QVERIFY(ctx3->activationObject().property("bar", QScriptValue::ResolveLocal).strictlyEquals(QScriptValue(&eng, "ciao"))); + + ctx3->activationObject().setProperty("baz", 789, QScriptValue::ReadOnly); + QVERIFY(eng.evaluate("baz").equals(789)); + QCOMPARE(ctx3->activationObject().propertyFlags("baz"), QScriptValue::ReadOnly); + + QSet activationPropertyNames; + QScriptValueIterator it(ctx3->activationObject()); + while (it.hasNext()) { + it.next(); + activationPropertyNames.insert(it.name()); + } + QCOMPARE(activationPropertyNames.size(), 4); + QVERIFY(activationPropertyNames.contains("foo")); + QVERIFY(activationPropertyNames.contains("4")); + QVERIFY(activationPropertyNames.contains("bar")); + QVERIFY(activationPropertyNames.contains("baz")); + eng.popContext(); } @@ -1054,6 +1078,20 @@ void tst_QScriptContext::getSetActivationObject() } } +void tst_QScriptContext::getSetActivationObject_customContext() +{ + QScriptEngine eng; + QScriptContext *ctx = eng.pushContext(); + QVERIFY(ctx->activationObject().isObject()); + QScriptValue act = eng.newObject(); + ctx->setActivationObject(act); + QVERIFY(ctx->activationObject().equals(act)); + eng.evaluate("var foo = 123"); + QCOMPARE(act.property("foo").toInt32(), 123); + eng.popContext(); + QCOMPARE(act.property("foo").toInt32(), 123); +} + static QScriptValue myEval(QScriptContext *ctx, QScriptEngine *eng) { QString code = ctx->argument(0).toString(); diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 3a376ec..034512f 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -130,6 +130,7 @@ private slots: void gcWithNestedDataStructure(); void processEventsWhileRunning(); void throwErrorFromProcessEvents(); + void disableProcessEventsInterval(); void stacktrace(); void numberParsing_data(); void numberParsing(); @@ -170,6 +171,7 @@ private slots: void evaluateProgram(); void collectGarbageAfterConnect(); void promoteThisObjectToQObjectInConstructor(); + void scriptValueFromQMetaObject(); void qRegExpInport_data(); void qRegExpInport(); @@ -457,11 +459,13 @@ void tst_QScriptEngine::newVariant() // replace value of existing object { QScriptValue object = eng.newVariant(QVariant(123)); - QScriptValue ret = eng.newVariant(object, QVariant(456)); - QVERIFY(ret.isValid()); - QVERIFY(ret.strictlyEquals(object)); - QVERIFY(ret.isVariant()); - QCOMPARE(ret.toVariant(), QVariant(456)); + for (int x = 0; x < 2; ++x) { + QScriptValue ret = eng.newVariant(object, QVariant(456)); + QVERIFY(ret.isValid()); + QVERIFY(ret.strictlyEquals(object)); + QVERIFY(ret.isVariant()); + QCOMPARE(ret.toVariant(), QVariant(456)); + } } // valueOf() and toString() @@ -496,6 +500,19 @@ void tst_QScriptEngine::newVariant() QVERIFY(value.strictlyEquals(object)); QCOMPARE(object.toString(), QString::fromLatin1("QVariant(QPoint)")); } + + { + QVariant var(456); + QScriptValue ret = eng.newVariant(123, var); + QVERIFY(ret.isVariant()); + QCOMPARE(ret.toVariant(), var); + } + + { + QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::newVariant(): changing class of non-QScriptObject not supported"); + QScriptValue ret = eng.newVariant(eng.newArray(), 123); + QVERIFY(!ret.isValid()); + } } void tst_QScriptEngine::newRegExp() @@ -734,12 +751,14 @@ void tst_QScriptEngine::newQObject() QScriptValue object = eng.newVariant(123); QScriptValue originalProto = object.prototype(); QObject otherQObject; - QScriptValue ret = eng.newQObject(object, &otherQObject); - QVERIFY(ret.isValid()); - QVERIFY(ret.isQObject()); - QVERIFY(ret.strictlyEquals(object)); - QCOMPARE(ret.toQObject(), (QObject *)&otherQObject); - QVERIFY(ret.prototype().strictlyEquals(originalProto)); + for (int x = 0; x < 2; ++x) { + QScriptValue ret = eng.newQObject(object, &otherQObject); + QVERIFY(ret.isValid()); + QVERIFY(ret.isQObject()); + QVERIFY(ret.strictlyEquals(object)); + QCOMPARE(ret.toQObject(), (QObject *)&otherQObject); + QVERIFY(ret.prototype().strictlyEquals(originalProto)); + } } // calling newQObject() several times with same object @@ -794,6 +813,18 @@ void tst_QScriptEngine::newQObject() eng.setDefaultPrototype(qMetaTypeId(), oldQObjectProto); eng.setDefaultPrototype(typeId, QScriptValue()); } + + { + QScriptValue ret = eng.newQObject(123, this); + QVERIFY(ret.isQObject()); + QCOMPARE(ret.toQObject(), this); + } + + { + QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::newQObject(): changing class of non-QScriptObject not supported"); + QScriptValue ret = eng.newQObject(eng.newArray(), this); + QVERIFY(!ret.isValid()); + } } QT_BEGIN_NAMESPACE @@ -982,6 +1013,11 @@ void tst_QScriptEngine::getSetGlobalObject() QCOMPARE(glob.prototype().isObject(), true); QCOMPARE(glob.prototype().strictlyEquals(eng.evaluate("Object.prototype")), true); + eng.setGlobalObject(glob); + QVERIFY(eng.globalObject().equals(glob)); + eng.setGlobalObject(123); + QVERIFY(eng.globalObject().equals(glob)); + QScriptValue obj = eng.newObject(); eng.setGlobalObject(obj); QVERIFY(eng.globalObject().strictlyEquals(obj)); @@ -1031,6 +1067,28 @@ void tst_QScriptEngine::getSetGlobalObject() QScriptValue ret = eng.evaluate("(function() { return this; })()"); QVERIFY(ret.strictlyEquals(obj)); } + + // Delete property. + { + QScriptValue ret = eng.evaluate("delete foo"); + QVERIFY(ret.isBool()); + QVERIFY(ret.toBool()); + QVERIFY(!obj.property("foo").isValid()); + } + + // Getter/setter property. + QVERIFY(eng.evaluate("this.__defineGetter__('oof', function() { return this.bar; })").isUndefined()); + QVERIFY(eng.evaluate("this.__defineSetter__('oof', function(v) { this.bar = v; })").isUndefined()); + QVERIFY(eng.evaluate("this.__lookupGetter__('oof')").isFunction()); + QVERIFY(eng.evaluate("this.__lookupSetter__('oof')").isFunction()); + eng.evaluate("oof = 123"); + QVERIFY(eng.evaluate("oof").equals(obj.property("bar"))); + + // Enumeration. + { + QScriptValue ret = eng.evaluate("a = []; for (var p in this) a.push(p); a"); + QCOMPARE(ret.toString(), QString::fromLatin1("bar,baz,oof,p,a")); + } } static QScriptValue getSetFoo(QScriptContext *ctx, QScriptEngine *) @@ -2257,6 +2315,8 @@ void tst_QScriptEngine::valueConversion() QEXPECT_FAIL("", "QTBUG-6136: JSC-based back-end doesn't preserve QRegExp::minimal (always false)", Continue); QCOMPARE(val.toRegExp().isMinimal(), in.isMinimal()); } + + QCOMPARE(qscriptvalue_cast(QScriptValue(123)), QVariant(123)); } void tst_QScriptEngine::qScriptValueFromValue_noEngine() @@ -2701,6 +2761,19 @@ void tst_QScriptEngine::throwErrorFromProcessEvents() QCOMPARE(ret.toString(), QString::fromLatin1("Error: Killed")); } +void tst_QScriptEngine::disableProcessEventsInterval() +{ + QScriptEngine eng; + eng.setProcessEventsInterval(100); + QCOMPARE(eng.processEventsInterval(), 100); + eng.setProcessEventsInterval(0); + QCOMPARE(eng.processEventsInterval(), 0); + eng.setProcessEventsInterval(-1); + QCOMPARE(eng.processEventsInterval(), -1); + eng.setProcessEventsInterval(-100); + QCOMPARE(eng.processEventsInterval(), -100); +} + void tst_QScriptEngine::stacktrace() { QString script = QString::fromLatin1( @@ -4529,6 +4602,17 @@ void tst_QScriptEngine::installTranslatorFunctions() QVERIFY(ret.isString()); QCOMPARE(ret.toString(), QString::fromLatin1("foobar")); } + { + QScriptValue ret = eng.evaluate("'foo%0'.arg(123)"); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString::fromLatin1("foo123")); + } + { + // Maybe this should throw an error? + QScriptValue ret = eng.evaluate("'foo%0'.arg()"); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString()); + } { QScriptValue ret = eng.evaluate("qsTrId('foo')"); @@ -4540,6 +4624,7 @@ void tst_QScriptEngine::installTranslatorFunctions() QVERIFY(ret.isString()); QCOMPARE(ret.toString(), QString::fromLatin1("foo")); } + QVERIFY(eng.evaluate("QT_TRID_NOOP()").isUndefined()); } static QScriptValue callQsTr(QScriptContext *ctx, QScriptEngine *eng) @@ -4574,9 +4659,14 @@ void tst_QScriptEngine::translateScript() QCOMPARE(engine.evaluate("eval('qsTranslate(\\'FooContext\\', \\'Goodbye\\')')", fileName).toString(), QString::fromLatin1("Farvel")); QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Goodbye', '', 'UnicodeUTF8')", fileName).toString(), QString::fromLatin1("Farvel")); + QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Goodbye', '', 'CodecForTr')", fileName).toString(), QString::fromLatin1("Farvel")); + + QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Goodbye', '', 'UnicodeUTF8', 42)", fileName).toString(), QString::fromLatin1("Goodbye")); QCOMPARE(engine.evaluate("qsTr('One', 'not the same one')", fileName).toString(), QString::fromLatin1("Enda en")); + QCOMPARE(engine.evaluate("qsTr('One', 'not the same one', 42)", fileName).toString(), QString::fromLatin1("One")); + QVERIFY(engine.evaluate("QT_TR_NOOP()").isUndefined()); QCOMPARE(engine.evaluate("QT_TR_NOOP('One')").toString(), QString::fromLatin1("One")); @@ -4645,6 +4735,7 @@ void tst_QScriptEngine::translateWithInvalidArgs_data() QTest::newRow("qsTranslate()") << "qsTranslate()" << "Error: qsTranslate() requires at least two arguments"; QTest::newRow("qsTranslate('foo')") << "qsTranslate('foo')" << "Error: qsTranslate() requires at least two arguments"; + QTest::newRow("qsTranslate(123, 'foo')") << "qsTranslate(123, 'foo')" << "Error: qsTranslate(): first argument (context) must be a string"; QTest::newRow("qsTranslate('foo', 123)") << "qsTranslate('foo', 123)" << "Error: qsTranslate(): second argument (text) must be a string"; QTest::newRow("qsTranslate('foo', 'bar', 123)") << "qsTranslate('foo', 'bar', 123)" << "Error: qsTranslate(): third argument (comment) must be a string"; QTest::newRow("qsTranslate('foo', 'bar', 'baz', 123)") << "qsTranslate('foo', 'bar', 'baz', 123)" << "Error: qsTranslate(): fourth argument (encoding) must be a string"; @@ -5108,6 +5199,10 @@ void tst_QScriptEngine::qRegExpInport_data() QTest::newRow("aaa") << QRegExp("a{2,5}") << "aAaAaaaaaAa"; QTest::newRow("aaa minimal") << minimal(QRegExp("a{2,5}")) << "aAaAaaaaaAa"; QTest::newRow("minimal") << minimal(QRegExp(".*\\} [*8]")) << "}?} ?} *"; + QTest::newRow(".? minimal") << minimal(QRegExp(".?")) << ".?"; + QTest::newRow(".+ minimal") << minimal(QRegExp(".+")) << ".+"; + QTest::newRow("[.?] minimal") << minimal(QRegExp("[.?]")) << ".?"; + QTest::newRow("[.+] minimal") << minimal(QRegExp("[.+]")) << ".+"; } void tst_QScriptEngine::qRegExpInport() @@ -5452,5 +5547,29 @@ void tst_QScriptEngine::newGrowingStaticScopeObject() eng.popContext(); } +Q_SCRIPT_DECLARE_QMETAOBJECT(QStandardItemModel, QObject*) + +void tst_QScriptEngine::scriptValueFromQMetaObject() +{ + QScriptEngine eng; + { + QScriptValue meta = eng.scriptValueFromQMetaObject(); + QVERIFY(meta.isQMetaObject()); + QCOMPARE(meta.toQMetaObject(), &QScriptEngine::staticMetaObject); + // Because of missing Q_SCRIPT_DECLARE_QMETAOBJECT() for QScriptEngine. + QVERIFY(!meta.construct().isValid()); + } + { + QScriptValue meta = eng.scriptValueFromQMetaObject(); + QVERIFY(meta.isQMetaObject()); + QCOMPARE(meta.toQMetaObject(), &QStandardItemModel::staticMetaObject); + QScriptValue obj = meta.construct(QScriptValueList() << eng.newQObject(&eng)); + QVERIFY(obj.isQObject()); + QStandardItemModel *model = qobject_cast(obj.toQObject()); + QVERIFY(model != 0); + QCOMPARE(model->parent(), (QObject*)&eng); + } +} + QTEST_MAIN(tst_QScriptEngine) #include "tst_qscriptengine.moc" diff --git a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp index 0d57f0c..1562118 100644 --- a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp +++ b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp @@ -329,6 +329,18 @@ public: { m_qtFunctionInvoked = 58; m_actuals << int(arg); return arg; } Q_INVOKABLE MyQObject::Ability myInvokableWithQualifiedFlagsArg(MyQObject::Ability arg) { m_qtFunctionInvoked = 59; m_actuals << int(arg); return arg; } + Q_INVOKABLE QWidget *myInvokableWithQWidgetStarArg(QWidget *arg) + { m_qtFunctionInvoked = 63; m_actuals << qVariantFromValue((QWidget*)arg); return arg; } + Q_INVOKABLE short myInvokableWithShortArg(short arg) + { m_qtFunctionInvoked = 64; m_actuals << qVariantFromValue(arg); return arg; } + Q_INVOKABLE unsigned short myInvokableWithUShortArg(unsigned short arg) + { m_qtFunctionInvoked = 65; m_actuals << qVariantFromValue(arg); return arg; } + Q_INVOKABLE char myInvokableWithCharArg(char arg) + { m_qtFunctionInvoked = 66; m_actuals << qVariantFromValue(arg); return arg; } + Q_INVOKABLE unsigned char myInvokableWithUCharArg(unsigned char arg) + { m_qtFunctionInvoked = 67; m_actuals << qVariantFromValue(arg); return arg; } + Q_INVOKABLE qulonglong myInvokableWithULonglongArg(qulonglong arg) + { m_qtFunctionInvoked = 68; m_actuals << qVariantFromValue(arg); return arg; } Q_INVOKABLE QObjectList findObjects() const { return findChildren(); } @@ -394,6 +406,8 @@ public Q_SLOTS: { m_qtFunctionInvoked = 32; m_actuals << arg; } void myOverloadedSlot(const QDate &arg) { m_qtFunctionInvoked = 33; m_actuals << arg; } + void myOverloadedSlot(const QTime &arg) + { m_qtFunctionInvoked = 69; m_actuals << arg; } void myOverloadedSlot(const QRegExp &arg) { m_qtFunctionInvoked = 34; m_actuals << arg; } void myOverloadedSlot(const QVariant &arg) @@ -519,6 +533,7 @@ private slots: void callQtInvokable(); void connectAndDisconnect(); void connectAndDisconnectWithBadArgs(); + void connectAndDisconnect_senderDeleted(); void cppConnectAndDisconnect(); void classEnums(); void classConstructor(); @@ -1361,6 +1376,17 @@ void tst_QScriptExtQObject::callQtInvokable() m_myObject->resetQtFunctionInvoked(); { + QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithQWidgetStarArg(null)"); + QVERIFY(ret.isNull()); + QCOMPARE(m_myObject->qtFunctionInvoked(), 63); + QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); + QVariant v = m_myObject->qtFunctionActuals().at(0); + QCOMPARE(v.userType(), int(QMetaType::QWidgetStar)); + QCOMPARE(qvariant_cast(v), (QObject *)0); + } + + m_myObject->resetQtFunctionInvoked(); + { // no implicit conversion from integer to QObject* QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithQObjectStarArg(123)"); QCOMPARE(ret.isError(), true); @@ -1368,6 +1394,61 @@ void tst_QScriptExtQObject::callQtInvokable() m_myObject->resetQtFunctionInvoked(); { + QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithShortArg(123)"); + QVERIFY(ret.isNumber()); + QCOMPARE(m_myObject->qtFunctionInvoked(), 64); + QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); + QVariant v = m_myObject->qtFunctionActuals().at(0); + QCOMPARE(v.userType(), int(QMetaType::Short)); + QCOMPARE(qvariant_cast(v), short(123)); + } + + m_myObject->resetQtFunctionInvoked(); + { + QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithUShortArg(123)"); + QVERIFY(ret.isNumber()); + QCOMPARE(m_myObject->qtFunctionInvoked(), 65); + QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); + QVariant v = m_myObject->qtFunctionActuals().at(0); + QCOMPARE(v.userType(), int(QMetaType::UShort)); + QCOMPARE(qvariant_cast(v), ushort(123)); + } + + m_myObject->resetQtFunctionInvoked(); + { + QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithCharArg(123)"); + QVERIFY(ret.isNumber()); + QCOMPARE(m_myObject->qtFunctionInvoked(), 66); + QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); + QVariant v = m_myObject->qtFunctionActuals().at(0); + QCOMPARE(v.userType(), int(QMetaType::Char)); + QCOMPARE(qvariant_cast(v), char(123)); + } + + m_myObject->resetQtFunctionInvoked(); + { + QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithUCharArg(123)"); + QVERIFY(ret.isNumber()); + QCOMPARE(m_myObject->qtFunctionInvoked(), 67); + QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); + QVariant v = m_myObject->qtFunctionActuals().at(0); + QCOMPARE(v.userType(), int(QMetaType::UChar)); + QCOMPARE(qvariant_cast(v), uchar(123)); + } + + m_myObject->resetQtFunctionInvoked(); + { + QScriptValue ret = m_engine->evaluate("myObject.myInvokableWithULonglongArg(123)"); + QVERIFY(ret.isNumber()); + QCOMPARE(m_myObject->qtFunctionInvoked(), 68); + QCOMPARE(m_myObject->qtFunctionActuals().size(), 1); + QVariant v = m_myObject->qtFunctionActuals().at(0); + QCOMPARE(v.userType(), int(QMetaType::ULongLong)); + QCOMPARE(qvariant_cast(v), qulonglong(123)); + } + + m_myObject->resetQtFunctionInvoked(); + { QScriptValue fun = m_engine->evaluate("myObject.myInvokableWithQBrushArg"); QVERIFY(fun.isFunction()); QColor color(10, 20, 30, 40); @@ -1916,6 +1997,25 @@ void tst_QScriptExtQObject::connectAndDisconnectWithBadArgs() } } +void tst_QScriptExtQObject::connectAndDisconnect_senderDeleted() +{ + QScriptEngine eng; + QObject *obj = new QObject; + eng.globalObject().setProperty("obj", eng.newQObject(obj)); + eng.evaluate("signal = obj.destroyed"); + delete obj; + { + QScriptValue ret = eng.evaluate("signal.connect(function(){})"); + QVERIFY(ret.isError()); + QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Function.prototype.connect: cannot connect to deleted QObject")); + } + { + QScriptValue ret = eng.evaluate("signal.disconnect(function(){})"); + QVERIFY(ret.isError()); + QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Function.prototype.discconnect: cannot disconnect from deleted QObject")); + } +} + void tst_QScriptExtQObject::cppConnectAndDisconnect() { QScriptEngine eng; diff --git a/tests/auto/qscriptvalueiterator/tst_qscriptvalueiterator.cpp b/tests/auto/qscriptvalueiterator/tst_qscriptvalueiterator.cpp index 55773f0..df11537 100644 --- a/tests/auto/qscriptvalueiterator/tst_qscriptvalueiterator.cpp +++ b/tests/auto/qscriptvalueiterator/tst_qscriptvalueiterator.cpp @@ -71,6 +71,7 @@ private slots: void iterateString(); void iterateGetterSetter(); void assignObjectToIterator(); + void iterateNonObject(); }; tst_QScriptValueIterator::tst_QScriptValueIterator() @@ -583,5 +584,25 @@ void tst_QScriptValueIterator::assignObjectToIterator() QCOMPARE(it.name(), QString::fromLatin1("bar")); } +void tst_QScriptValueIterator::iterateNonObject() +{ + QScriptValueIterator it(123); + QVERIFY(!it.hasNext()); + it.next(); + QVERIFY(!it.hasPrevious()); + it.previous(); + it.toFront(); + it.toBack(); + it.name(); + it.scriptName(); + it.flags(); + it.value(); + it.setValue(1); + it.remove(); + QScriptValue num(5); + it = num; + QVERIFY(!it.hasNext()); +} + QTEST_MAIN(tst_QScriptValueIterator) #include "tst_qscriptvalueiterator.moc" -- cgit v0.12 From 8cd4b7622ea425f8fef316ae4ae91133f29f53c5 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 29 Oct 2010 15:22:19 +0200 Subject: Add autotest for QScriptExtensionPlugin It's only about four years overdue. --- .../qscriptextensionplugin.pro | 3 + .../simpleplugin/simpleplugin.cpp | 79 ++++++++++ .../simpleplugin/simpleplugin.pro | 10 ++ .../staticplugin/__init__.js | 6 + .../staticplugin/staticplugin.cpp | 75 +++++++++ .../staticplugin/staticplugin.pro | 7 + .../staticplugin/staticplugin.qrc | 6 + tests/auto/qscriptextensionplugin/test/test.pro | 18 +++ .../tst_qscriptextensionplugin.cpp | 167 +++++++++++++++++++++ tests/auto/script.pro | 1 + 10 files changed, 372 insertions(+) create mode 100644 tests/auto/qscriptextensionplugin/qscriptextensionplugin.pro create mode 100644 tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.cpp create mode 100644 tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.pro create mode 100644 tests/auto/qscriptextensionplugin/staticplugin/__init__.js create mode 100644 tests/auto/qscriptextensionplugin/staticplugin/staticplugin.cpp create mode 100644 tests/auto/qscriptextensionplugin/staticplugin/staticplugin.pro create mode 100644 tests/auto/qscriptextensionplugin/staticplugin/staticplugin.qrc create mode 100644 tests/auto/qscriptextensionplugin/test/test.pro create mode 100644 tests/auto/qscriptextensionplugin/tst_qscriptextensionplugin.cpp diff --git a/tests/auto/qscriptextensionplugin/qscriptextensionplugin.pro b/tests/auto/qscriptextensionplugin/qscriptextensionplugin.pro new file mode 100644 index 0000000..d4671c8 --- /dev/null +++ b/tests/auto/qscriptextensionplugin/qscriptextensionplugin.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +CONFIG -= app_bundle +SUBDIRS = simpleplugin staticplugin test diff --git a/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.cpp b/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.cpp new file mode 100644 index 0000000..1679512 --- /dev/null +++ b/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +class SimplePlugin : public QScriptExtensionPlugin +{ +public: + SimplePlugin(QObject *parent = 0); + ~SimplePlugin(); + + virtual QStringList keys() const; + virtual void initialize(const QString &key, QScriptEngine *engine); +}; + +SimplePlugin::SimplePlugin(QObject *parent) + : QScriptExtensionPlugin(parent) +{ +} + +SimplePlugin::~SimplePlugin() +{ +} + +QStringList SimplePlugin::keys() const +{ + return QStringList() << "simple" + << "simple.foo" + << "simple.foo.bar"; +} + +void SimplePlugin::initialize(const QString &key, QScriptEngine *engine) +{ + engine->globalObject().setProperty("pluginKey", key); + QScriptValue package = setupPackage(key, engine); + engine->globalObject().setProperty("package", package); +} + +Q_EXPORT_PLUGIN2(simpleplugin, SimplePlugin) diff --git a/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.pro b/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.pro new file mode 100644 index 0000000..e184ca4 --- /dev/null +++ b/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.pro @@ -0,0 +1,10 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = simpleplugin.cpp +QT = core script +TARGET = simpleplugin +DESTDIR = ../plugins/script + +symbian { + TARGET.EPOCALLOWDLLDATA=1 +} diff --git a/tests/auto/qscriptextensionplugin/staticplugin/__init__.js b/tests/auto/qscriptextensionplugin/staticplugin/__init__.js new file mode 100644 index 0000000..4e462ae --- /dev/null +++ b/tests/auto/qscriptextensionplugin/staticplugin/__init__.js @@ -0,0 +1,6 @@ +spy = { + extension: __extension__, + setupPackage: __setupPackage__, + postInit: __postInit__ +}; +__postInit__ = function() { postInitWasCalled = true; }; diff --git a/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.cpp b/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.cpp new file mode 100644 index 0000000..b13f723 --- /dev/null +++ b/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +class StaticPlugin : public QScriptExtensionPlugin +{ +public: + StaticPlugin(QObject *parent = 0); + ~StaticPlugin(); + + virtual QStringList keys() const; + virtual void initialize(const QString &key, QScriptEngine *engine); +}; + +StaticPlugin::StaticPlugin(QObject *parent) + : QScriptExtensionPlugin(parent) +{ +} + +StaticPlugin::~StaticPlugin() +{ +} + +QStringList StaticPlugin::keys() const +{ + return QStringList() << "static"; +} + +void StaticPlugin::initialize(const QString &key, QScriptEngine *engine) +{ + engine->globalObject().setProperty("pluginKey", key); +} + +Q_EXPORT_PLUGIN2(staticplugin, StaticPlugin) diff --git a/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.pro b/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.pro new file mode 100644 index 0000000..a003338 --- /dev/null +++ b/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.pro @@ -0,0 +1,7 @@ +TEMPLATE = lib +CONFIG += static plugin +SOURCES = staticplugin.cpp +RESOURCES = staticplugin.qrc +QT = core script +TARGET = staticplugin +DESTDIR = ../plugins/script diff --git a/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.qrc b/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.qrc new file mode 100644 index 0000000..293bf0e --- /dev/null +++ b/tests/auto/qscriptextensionplugin/staticplugin/staticplugin.qrc @@ -0,0 +1,6 @@ + + +__init__.js + + + diff --git a/tests/auto/qscriptextensionplugin/test/test.pro b/tests/auto/qscriptextensionplugin/test/test.pro new file mode 100644 index 0000000..549bac2 --- /dev/null +++ b/tests/auto/qscriptextensionplugin/test/test.pro @@ -0,0 +1,18 @@ +load(qttest_p4) + +QT = core script +SOURCES = ../tst_qscriptextensionplugin.cpp +CONFIG -= app_bundle +LIBS += -L../plugins/script -lstaticplugin + +TARGET = tst_qscriptextensionplugin +CONFIG(debug_and_release) { + CONFIG(debug, debug|release) { + DESTDIR = ../debug + } else { + DESTDIR = ../release + } +} else { + DESTDIR = .. +} + diff --git a/tests/auto/qscriptextensionplugin/tst_qscriptextensionplugin.cpp b/tests/auto/qscriptextensionplugin/tst_qscriptextensionplugin.cpp new file mode 100644 index 0000000..e8b5e0a --- /dev/null +++ b/tests/auto/qscriptextensionplugin/tst_qscriptextensionplugin.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include + +#include + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QScriptExtensionPlugin : public QObject +{ + Q_OBJECT + +public: + tst_QScriptExtensionPlugin(); + virtual ~tst_QScriptExtensionPlugin(); + +private slots: + void importSimplePlugin(); + void importStaticPlugin(); +}; + +tst_QScriptExtensionPlugin::tst_QScriptExtensionPlugin() +{ +} + +tst_QScriptExtensionPlugin::~tst_QScriptExtensionPlugin() +{ +} + +void tst_QScriptExtensionPlugin::importSimplePlugin() +{ + QScriptEngine eng; + QCoreApplication::addLibraryPath("plugins"); + + QVERIFY(eng.importedExtensions().isEmpty()); + + QStringList available = eng.availableExtensions(); + QVERIFY(available.contains("simple")); + QVERIFY(available.contains("simple.foo")); + QVERIFY(available.contains("simple.foo.bar")); + + QScriptValue extensionObject; + { + QVERIFY(eng.importExtension("simple").isUndefined()); + QCOMPARE(eng.importedExtensions().size(), 1); + QCOMPARE(eng.importedExtensions().at(0), QString::fromLatin1("simple")); + QVERIFY(eng.availableExtensions().contains("simple")); + QVERIFY(eng.globalObject().property("pluginKey").equals("simple")); + QVERIFY(eng.globalObject().property("package").isObject()); + extensionObject = eng.globalObject().property("simple"); + QVERIFY(extensionObject.isObject()); + QVERIFY(extensionObject.equals(eng.globalObject().property("package"))); + } + + { + QVERIFY(eng.importExtension("simple.foo").isUndefined()); + QCOMPARE(eng.importedExtensions().size(), 2); + QCOMPARE(eng.importedExtensions().at(1), QString::fromLatin1("simple.foo")); + QVERIFY(eng.availableExtensions().contains("simple.foo")); + QVERIFY(eng.globalObject().property("pluginKey").equals("simple.foo")); + QVERIFY(eng.globalObject().property("package").isObject()); + QVERIFY(!extensionObject.equals(eng.globalObject().property("package"))); + QVERIFY(extensionObject.equals(eng.globalObject().property("simple"))); + QVERIFY(extensionObject.property("foo").isObject()); + QVERIFY(extensionObject.property("foo").equals(eng.globalObject().property("package"))); + } + + { + QVERIFY(eng.importExtension("simple.foo.bar").isUndefined()); + QCOMPARE(eng.importedExtensions().size(), 3); + QCOMPARE(eng.importedExtensions().at(2), QString::fromLatin1("simple.foo.bar")); + QVERIFY(eng.availableExtensions().contains("simple.foo.bar")); + QVERIFY(eng.globalObject().property("pluginKey").equals("simple.foo.bar")); + QVERIFY(eng.globalObject().property("package").isObject()); + QVERIFY(!extensionObject.equals(eng.globalObject().property("package"))); + QVERIFY(extensionObject.equals(eng.globalObject().property("simple"))); + QVERIFY(extensionObject.property("foo").property("bar").isObject()); + QVERIFY(extensionObject.property("foo").property("bar").equals(eng.globalObject().property("package"))); + } + + // Extensions can't be imported multiple times. + eng.globalObject().setProperty("pluginKey", QScriptValue()); + QVERIFY(eng.importExtension("simple").isUndefined()); + QCOMPARE(eng.importedExtensions().size(), 3); + QVERIFY(!eng.globalObject().property("pluginKey").isValid()); + + QVERIFY(eng.importExtension("simple.foo").isUndefined()); + QCOMPARE(eng.importedExtensions().size(), 3); + QVERIFY(!eng.globalObject().property("pluginKey").isValid()); + + QVERIFY(eng.importExtension("simple.foo.bar").isUndefined()); + QCOMPARE(eng.importedExtensions().size(), 3); + QVERIFY(!eng.globalObject().property("pluginKey").isValid()); +} + +void tst_QScriptExtensionPlugin::importStaticPlugin() +{ + Q_INIT_RESOURCE(staticplugin); + QScriptEngine eng; + QVERIFY(eng.availableExtensions().contains("static")); + QVERIFY(eng.importExtension("static").isUndefined()); + QCOMPARE(eng.importedExtensions().size(), 1); + QCOMPARE(eng.importedExtensions().at(0), QString::fromLatin1("static")); + QVERIFY(eng.availableExtensions().contains("static")); + QVERIFY(eng.globalObject().property("pluginKey").equals("static")); + + // Verify that :/qtscriptextension/static/__init__.js was evaluated. + QVERIFY(eng.evaluate("spy").isObject()); + QVERIFY(eng.evaluate("spy.extension").equals("static")); + QVERIFY(eng.evaluate("spy.setupPackage").isFunction()); + QVERIFY(eng.evaluate("spy.postInit").isUndefined()); + + QVERIFY(eng.evaluate("postInitWasCalled").isBool()); + QVERIFY(eng.evaluate("postInitWasCalled").toBool()); + + // Extensions can't be imported multiple times. + eng.globalObject().setProperty("pluginKey", QScriptValue()); + QVERIFY(eng.importExtension("static").isUndefined()); + QCOMPARE(eng.importedExtensions().size(), 1); + QVERIFY(!eng.globalObject().property("pluginKey").isValid()); +} + +Q_IMPORT_PLUGIN(staticplugin) + +QTEST_MAIN(tst_QScriptExtensionPlugin) +#include "tst_qscriptextensionplugin.moc" diff --git a/tests/auto/script.pro b/tests/auto/script.pro index 06f51b5..420bd74 100644 --- a/tests/auto/script.pro +++ b/tests/auto/script.pro @@ -7,6 +7,7 @@ SUBDIRS=\ qscriptengine \ qscriptengineagent \ qscriptenginedebugger \ + qscriptextensionplugin \ qscriptextqobject \ qscriptjstestsuite \ qscriptstring \ -- cgit v0.12