summaryrefslogtreecommitdiffstats
path: root/util/cmake/tests
diff options
context:
space:
mode:
Diffstat (limited to 'util/cmake/tests')
-rw-r--r--util/cmake/tests/__init__.py0
-rw-r--r--util/cmake/tests/data/comment_scope.pro6
-rw-r--r--util/cmake/tests/data/complex_assign.pro2
-rw-r--r--util/cmake/tests/data/complex_condition.pro4
-rw-r--r--util/cmake/tests/data/complex_values.pro22
-rw-r--r--util/cmake/tests/data/condition_without_scope.pro2
-rw-r--r--util/cmake/tests/data/contains_scope.pro4
-rw-r--r--util/cmake/tests/data/definetest.pro6
-rw-r--r--util/cmake/tests/data/else.pro6
-rw-r--r--util/cmake/tests/data/else2.pro4
-rw-r--r--util/cmake/tests/data/else3.pro7
-rw-r--r--util/cmake/tests/data/else4.pro6
-rw-r--r--util/cmake/tests/data/else5.pro10
-rw-r--r--util/cmake/tests/data/else6.pro11
-rw-r--r--util/cmake/tests/data/else7.pro2
-rw-r--r--util/cmake/tests/data/else8.pro5
-rw-r--r--util/cmake/tests/data/escaped_value.pro2
-rw-r--r--util/cmake/tests/data/for.pro11
-rw-r--r--util/cmake/tests/data/function_if.pro4
-rw-r--r--util/cmake/tests/data/include.pro3
-rw-r--r--util/cmake/tests/data/lc.pro10
-rw-r--r--util/cmake/tests/data/lc_with_comment.pro22
-rw-r--r--util/cmake/tests/data/load.pro3
-rw-r--r--util/cmake/tests/data/multi_condition_divided_by_lc.pro3
-rw-r--r--util/cmake/tests/data/multiline_assign.pro4
-rw-r--r--util/cmake/tests/data/nested_function_calls.pro2
-rw-r--r--util/cmake/tests/data/quoted.pro5
-rw-r--r--util/cmake/tests/data/single_line_for.pro4
-rw-r--r--util/cmake/tests/data/sql.pro3
-rw-r--r--util/cmake/tests/data/standardpaths.pro17
-rw-r--r--util/cmake/tests/data/unset.pro2
-rwxr-xr-xutil/cmake/tests/test_lc_fixup.py46
-rwxr-xr-xutil/cmake/tests/test_logic_mapping.py186
-rwxr-xr-xutil/cmake/tests/test_operations.py57
-rwxr-xr-xutil/cmake/tests/test_parsing.py345
-rwxr-xr-xutil/cmake/tests/test_scope_handling.py338
36 files changed, 1164 insertions, 0 deletions
diff --git a/util/cmake/tests/__init__.py b/util/cmake/tests/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/util/cmake/tests/__init__.py
diff --git a/util/cmake/tests/data/comment_scope.pro b/util/cmake/tests/data/comment_scope.pro
new file mode 100644
index 0000000000..be43cad37d
--- /dev/null
+++ b/util/cmake/tests/data/comment_scope.pro
@@ -0,0 +1,6 @@
+# QtCore can't be compiled with -Wl,-no-undefined because it uses the "environ"
+# variable and on FreeBSD and OpenBSD, this variable is in the final executable itself.
+# OpenBSD 6.0 will include environ in libc.
+freebsd|openbsd: QMAKE_LFLAGS_NOUNDEF =
+
+include(animation/animation.pri)
diff --git a/util/cmake/tests/data/complex_assign.pro b/util/cmake/tests/data/complex_assign.pro
new file mode 100644
index 0000000000..d251afcdd5
--- /dev/null
+++ b/util/cmake/tests/data/complex_assign.pro
@@ -0,0 +1,2 @@
+qmake-clean.commands += (cd qmake && $(MAKE) clean ":-(==)-:" '(Foo)' )
+
diff --git a/util/cmake/tests/data/complex_condition.pro b/util/cmake/tests/data/complex_condition.pro
new file mode 100644
index 0000000000..bc3369bd63
--- /dev/null
+++ b/util/cmake/tests/data/complex_condition.pro
@@ -0,0 +1,4 @@
+!system("dbus-send --session --type=signal / local.AutotestCheck.Hello >$$QMAKE_SYSTEM_NULL_DEVICE 2>&1") {
+ SOURCES = dbus.cpp
+}
+
diff --git a/util/cmake/tests/data/complex_values.pro b/util/cmake/tests/data/complex_values.pro
new file mode 100644
index 0000000000..4d747c1dd7
--- /dev/null
+++ b/util/cmake/tests/data/complex_values.pro
@@ -0,0 +1,22 @@
+linux:!static {
+ precompile_header {
+ # we'll get an error if we just use SOURCES +=
+ no_pch_assembler.commands = $$QMAKE_CC -c $(CFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
+ no_pch_assembler.dependency_type = TYPE_C
+ no_pch_assembler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
+ no_pch_assembler.input = NO_PCH_ASM
+ no_pch_assembler.name = compiling[no_pch] ${QMAKE_FILE_IN}
+ silent: no_pch_assembler.commands = @echo compiling[no_pch] ${QMAKE_FILE_IN} && $$no_pch_assembler.commands
+ CMAKE_ANGLE_GLES2_IMPLIB_RELEASE = libGLESv2.$${QMAKE_EXTENSION_STATICLIB}
+ HOST_BINS = $$[QT_HOST_BINS]
+ CMAKE_HOST_DATA_DIR = $$[QT_HOST_DATA/src]/
+ TR_EXCLUDE += ../3rdparty/*
+
+ QMAKE_EXTRA_COMPILERS += no_pch_assembler
+ NO_PCH_ASM += global/minimum-linux.S
+ } else {
+ SOURCES += global/minimum-linux.S
+ }
+ HEADERS += global/minimum-linux_p.h
+}
+
diff --git a/util/cmake/tests/data/condition_without_scope.pro b/util/cmake/tests/data/condition_without_scope.pro
new file mode 100644
index 0000000000..2aa1237c12
--- /dev/null
+++ b/util/cmake/tests/data/condition_without_scope.pro
@@ -0,0 +1,2 @@
+write_file("a", contents)|error()
+
diff --git a/util/cmake/tests/data/contains_scope.pro b/util/cmake/tests/data/contains_scope.pro
new file mode 100644
index 0000000000..0f51350a45
--- /dev/null
+++ b/util/cmake/tests/data/contains_scope.pro
@@ -0,0 +1,4 @@
+contains(DEFINES,QT_EVAL):include(eval.pri)
+
+HOST_BINS = $$[QT_HOST_BINS]
+
diff --git a/util/cmake/tests/data/definetest.pro b/util/cmake/tests/data/definetest.pro
new file mode 100644
index 0000000000..76b63d239f
--- /dev/null
+++ b/util/cmake/tests/data/definetest.pro
@@ -0,0 +1,6 @@
+defineTest(pathIsAbsolute) {
+ p = $$clean_path($$1)
+ !isEmpty(p):isEqual(p, $$absolute_path($$p)): return(true)
+ return(false)
+}
+
diff --git a/util/cmake/tests/data/else.pro b/util/cmake/tests/data/else.pro
new file mode 100644
index 0000000000..bbf9c5ac9f
--- /dev/null
+++ b/util/cmake/tests/data/else.pro
@@ -0,0 +1,6 @@
+
+linux {
+ SOURCES += a.cpp
+} else {
+ SOURCES += b.cpp
+}
diff --git a/util/cmake/tests/data/else2.pro b/util/cmake/tests/data/else2.pro
new file mode 100644
index 0000000000..f2ef36ec28
--- /dev/null
+++ b/util/cmake/tests/data/else2.pro
@@ -0,0 +1,4 @@
+
+osx: A = 1
+else: win32: B = 2
+else: C = 3
diff --git a/util/cmake/tests/data/else3.pro b/util/cmake/tests/data/else3.pro
new file mode 100644
index 0000000000..0de9c2c1d9
--- /dev/null
+++ b/util/cmake/tests/data/else3.pro
@@ -0,0 +1,7 @@
+qtConfig(timezone) {
+ A = 1
+} else:win32 {
+ B = 2
+} else {
+ C = 3
+}
diff --git a/util/cmake/tests/data/else4.pro b/util/cmake/tests/data/else4.pro
new file mode 100644
index 0000000000..9ed676ccfa
--- /dev/null
+++ b/util/cmake/tests/data/else4.pro
@@ -0,0 +1,6 @@
+qtConfig(timezone) {
+ A = 1
+} else:win32: B = 2
+else {
+ C = 3
+}
diff --git a/util/cmake/tests/data/else5.pro b/util/cmake/tests/data/else5.pro
new file mode 100644
index 0000000000..3de76af50a
--- /dev/null
+++ b/util/cmake/tests/data/else5.pro
@@ -0,0 +1,10 @@
+# comments
+qtConfig(timezone) { # bar
+ A = 1
+} else:win32 {
+ B = 2 # foo
+} else { C = 3
+# baz
+ # foobar
+}
+# endcomment
diff --git a/util/cmake/tests/data/else6.pro b/util/cmake/tests/data/else6.pro
new file mode 100644
index 0000000000..9eaa834a19
--- /dev/null
+++ b/util/cmake/tests/data/else6.pro
@@ -0,0 +1,11 @@
+qtConfig(timezone) \
+{
+ A = \
+1
+} \
+else:win32: \
+B = 2
+else: \
+ C \
+= 3
+
diff --git a/util/cmake/tests/data/else7.pro b/util/cmake/tests/data/else7.pro
new file mode 100644
index 0000000000..e663b1c05e
--- /dev/null
+++ b/util/cmake/tests/data/else7.pro
@@ -0,0 +1,2 @@
+msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x65000000
+
diff --git a/util/cmake/tests/data/else8.pro b/util/cmake/tests/data/else8.pro
new file mode 100644
index 0000000000..6d4d5f01ed
--- /dev/null
+++ b/util/cmake/tests/data/else8.pro
@@ -0,0 +1,5 @@
+qtConfig(timezone) { A = 1 } else:win32: {\
+B = 2 \
+} else: \
+ C \
+= 3 \
diff --git a/util/cmake/tests/data/escaped_value.pro b/util/cmake/tests/data/escaped_value.pro
new file mode 100644
index 0000000000..7c95b1fc30
--- /dev/null
+++ b/util/cmake/tests/data/escaped_value.pro
@@ -0,0 +1,2 @@
+MODULE_AUX_INCLUDES = \
+ \$\$QT_MODULE_INCLUDE_BASE/QtANGLE
diff --git a/util/cmake/tests/data/for.pro b/util/cmake/tests/data/for.pro
new file mode 100644
index 0000000000..5751432980
--- /dev/null
+++ b/util/cmake/tests/data/for.pro
@@ -0,0 +1,11 @@
+SOURCES = main.cpp
+for (config, SIMD) {
+ uc = $$upper($$config)
+ DEFINES += QT_COMPILER_SUPPORTS_$${uc}
+
+ add_cflags {
+ cflags = QMAKE_CFLAGS_$${uc}
+ !defined($$cflags, var): error("This compiler does not support $${uc}")
+ QMAKE_CXXFLAGS += $$eval($$cflags)
+ }
+}
diff --git a/util/cmake/tests/data/function_if.pro b/util/cmake/tests/data/function_if.pro
new file mode 100644
index 0000000000..9af018f864
--- /dev/null
+++ b/util/cmake/tests/data/function_if.pro
@@ -0,0 +1,4 @@
+pathIsAbsolute($$CMAKE_HOST_DATA_DIR) {
+ CMAKE_HOST_DATA_DIR = $$[QT_HOST_DATA/src]/
+}
+
diff --git a/util/cmake/tests/data/include.pro b/util/cmake/tests/data/include.pro
new file mode 100644
index 0000000000..22d8a40919
--- /dev/null
+++ b/util/cmake/tests/data/include.pro
@@ -0,0 +1,3 @@
+A = 42
+include(foo) # load foo
+B=23
diff --git a/util/cmake/tests/data/lc.pro b/util/cmake/tests/data/lc.pro
new file mode 100644
index 0000000000..def80e7c95
--- /dev/null
+++ b/util/cmake/tests/data/lc.pro
@@ -0,0 +1,10 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qmacstyle \
+ qstyle \
+ qstyleoption \
+ qstylesheetstyle \
+
+!qtConfig(private_tests): SUBDIRS -= \
+ qstylesheetstyle \
+
diff --git a/util/cmake/tests/data/lc_with_comment.pro b/util/cmake/tests/data/lc_with_comment.pro
new file mode 100644
index 0000000000..176913dfc8
--- /dev/null
+++ b/util/cmake/tests/data/lc_with_comment.pro
@@ -0,0 +1,22 @@
+SUBDIRS = \
+# dds \
+ tga \
+ wbmp
+
+MYVAR = foo # comment
+MYVAR = foo2# comment
+MYVAR = foo3# comment #
+
+MYVAR = foo4# comment #
+
+##
+#
+#
+##
+
+ #
+ #
+#
+ # #
+
+MYVAR = foo5# comment # #
diff --git a/util/cmake/tests/data/load.pro b/util/cmake/tests/data/load.pro
new file mode 100644
index 0000000000..c9717e9832
--- /dev/null
+++ b/util/cmake/tests/data/load.pro
@@ -0,0 +1,3 @@
+A = 42
+load(foo)# load foo
+B=23
diff --git a/util/cmake/tests/data/multi_condition_divided_by_lc.pro b/util/cmake/tests/data/multi_condition_divided_by_lc.pro
new file mode 100644
index 0000000000..23254231df
--- /dev/null
+++ b/util/cmake/tests/data/multi_condition_divided_by_lc.pro
@@ -0,0 +1,3 @@
+equals(a): \
+ greaterThan(a):flags += 1
+
diff --git a/util/cmake/tests/data/multiline_assign.pro b/util/cmake/tests/data/multiline_assign.pro
new file mode 100644
index 0000000000..42a3d0a674
--- /dev/null
+++ b/util/cmake/tests/data/multiline_assign.pro
@@ -0,0 +1,4 @@
+A = 42 \
+ 43 \
+ 44
+B=23
diff --git a/util/cmake/tests/data/nested_function_calls.pro b/util/cmake/tests/data/nested_function_calls.pro
new file mode 100644
index 0000000000..5ecc53f1cc
--- /dev/null
+++ b/util/cmake/tests/data/nested_function_calls.pro
@@ -0,0 +1,2 @@
+requires(qtConfig(dlopen))
+
diff --git a/util/cmake/tests/data/quoted.pro b/util/cmake/tests/data/quoted.pro
new file mode 100644
index 0000000000..61682aa0d0
--- /dev/null
+++ b/util/cmake/tests/data/quoted.pro
@@ -0,0 +1,5 @@
+if(linux*|hurd*):!cross_compile:!static:!*-armcc* {
+ prog=$$quote(if (/program interpreter: (.*)]/) { print $1; })
+ DEFINES += ELF_INTERPRETER=\\\"$$system(LC_ALL=C readelf -l /bin/ls | perl -n -e \'$$prog\')\\\"
+}
+
diff --git a/util/cmake/tests/data/single_line_for.pro b/util/cmake/tests/data/single_line_for.pro
new file mode 100644
index 0000000000..806d08a49c
--- /dev/null
+++ b/util/cmake/tests/data/single_line_for.pro
@@ -0,0 +1,4 @@
+for(d, sd): \
+ exists($$d/$${d}.pro): \
+ SUBDIRS += $$d
+
diff --git a/util/cmake/tests/data/sql.pro b/util/cmake/tests/data/sql.pro
new file mode 100644
index 0000000000..a9d7fc7c5a
--- /dev/null
+++ b/util/cmake/tests/data/sql.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ kernel \
diff --git a/util/cmake/tests/data/standardpaths.pro b/util/cmake/tests/data/standardpaths.pro
new file mode 100644
index 0000000000..4b45788e4f
--- /dev/null
+++ b/util/cmake/tests/data/standardpaths.pro
@@ -0,0 +1,17 @@
+win32 {
+ !winrt {
+ SOURCES +=io/qstandardpaths_win.cpp
+ } else {
+ SOURCES +=io/qstandardpaths_winrt.cpp
+ }
+} else:unix {
+ mac {
+ OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm
+ } else:android:!android-embedded {
+ SOURCES += io/qstandardpaths_android.cpp
+ } else:haiku {
+ SOURCES += io/qstandardpaths_haiku.cpp
+ } else {
+ SOURCES += io/qstandardpaths_unix.cpp
+ }
+}
diff --git a/util/cmake/tests/data/unset.pro b/util/cmake/tests/data/unset.pro
new file mode 100644
index 0000000000..7ffb0582f1
--- /dev/null
+++ b/util/cmake/tests/data/unset.pro
@@ -0,0 +1,2 @@
+unset(f16c_cxx)
+
diff --git a/util/cmake/tests/test_lc_fixup.py b/util/cmake/tests/test_lc_fixup.py
new file mode 100755
index 0000000000..841e11615e
--- /dev/null
+++ b/util/cmake/tests/test_lc_fixup.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the plugins of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from pro2cmake import fixup_linecontinuation
+
+
+def test_no_change():
+ input = "test \\\nline2\n line3"
+ output = "test line2\n line3"
+ result = fixup_linecontinuation(input)
+ assert output == result
+
+
+def test_fix():
+ input = "test \\\t\nline2\\\n line3\\ \nline4 \\ \t\nline5\\\n\n\n"
+ output = "test line2 line3 line4 line5 \n\n"
+ result = fixup_linecontinuation(input)
+ assert output == result
+
+
diff --git a/util/cmake/tests/test_logic_mapping.py b/util/cmake/tests/test_logic_mapping.py
new file mode 100755
index 0000000000..c477aa8351
--- /dev/null
+++ b/util/cmake/tests/test_logic_mapping.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python3
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the plugins of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from pro2cmake import simplify_condition
+
+
+def validate_simplify(input: str, expected: str) -> None:
+ output = simplify_condition(input)
+ assert output == expected
+
+
+def validate_simplify_unchanged(input: str) -> None:
+ validate_simplify(input, input)
+
+
+def test_simplify_on():
+ validate_simplify_unchanged('ON')
+
+
+def test_simplify_off():
+ validate_simplify_unchanged('OFF')
+
+
+def test_simplify_not_on():
+ validate_simplify('NOT ON', 'OFF')
+
+
+def test_simplify_not_off():
+ validate_simplify('NOT OFF', 'ON')
+
+
+def test_simplify_isEmpty():
+ validate_simplify_unchanged('isEmpty(foo)')
+
+
+def test_simplify_not_isEmpty():
+ validate_simplify_unchanged('NOT isEmpty(foo)')
+
+
+def test_simplify_simple_and():
+ validate_simplify_unchanged('QT_FEATURE_bar AND QT_FEATURE_foo')
+
+
+def test_simplify_simple_or():
+ validate_simplify_unchanged('QT_FEATURE_bar OR QT_FEATURE_foo')
+
+
+def test_simplify_simple_not():
+ validate_simplify_unchanged('NOT QT_FEATURE_foo')
+
+
+def test_simplify_simple_and_reorder():
+ validate_simplify('QT_FEATURE_foo AND QT_FEATURE_bar', 'QT_FEATURE_bar AND QT_FEATURE_foo')
+
+
+def test_simplify_simple_or_reorder():
+ validate_simplify('QT_FEATURE_foo OR QT_FEATURE_bar', 'QT_FEATURE_bar OR QT_FEATURE_foo')
+
+
+def test_simplify_unix_or_win32():
+ validate_simplify('WIN32 OR UNIX', 'ON')
+
+
+def test_simplify_unix_or_win32_or_foobar_or_barfoo():
+ validate_simplify('WIN32 OR UNIX OR foobar OR barfoo', 'ON')
+
+
+def test_simplify_not_not_bar():
+ validate_simplify(' NOT NOT bar ', 'bar')
+
+
+def test_simplify_not_unix():
+ validate_simplify('NOT UNIX', 'WIN32')
+
+
+def test_simplify_not_win32():
+ validate_simplify('NOT WIN32', 'UNIX')
+
+
+def test_simplify_unix_and_win32():
+ validate_simplify('WIN32 AND UNIX', 'OFF')
+
+
+def test_simplify_unix_or_win32():
+ validate_simplify('WIN32 OR UNIX', 'ON')
+
+
+def test_simplify_unix_and_win32_or_foobar_or_barfoo():
+ validate_simplify('WIN32 AND foobar AND UNIX AND barfoo', 'OFF')
+
+
+def test_simplify_watchos_and_win32():
+ validate_simplify('APPLE_WATCHOS AND WIN32', 'OFF')
+
+
+def test_simplify_win32_and_watchos():
+ validate_simplify('WIN32 AND APPLE_WATCHOS', 'OFF')
+
+
+def test_simplify_apple_and_appleosx():
+ validate_simplify('APPLE AND APPLE_OSX', 'APPLE_OSX')
+
+
+def test_simplify_apple_or_appleosx():
+ validate_simplify('APPLE OR APPLE_OSX', 'APPLE')
+
+
+def test_simplify_apple_or_appleosx_level1():
+ validate_simplify('foobar AND (APPLE OR APPLE_OSX )', 'APPLE AND foobar')
+
+
+def test_simplify_apple_or_appleosx_level1_double():
+ validate_simplify('foobar AND (APPLE OR APPLE_OSX )', 'APPLE AND foobar')
+
+
+def test_simplify_apple_or_appleosx_level1_double_with_extra_spaces():
+ validate_simplify('foobar AND (APPLE OR APPLE_OSX ) '
+ 'AND ( APPLE_OSX OR APPLE )', 'APPLE AND foobar')
+
+
+def test_simplify_apple_or_appleosx_level2():
+ validate_simplify('foobar AND ( ( APPLE OR APPLE_WATCHOS ) '
+ 'OR APPLE_OSX ) AND ( APPLE_OSX OR APPLE ) '
+ 'AND ( (WIN32 OR WINRT) OR UNIX) ', 'APPLE AND foobar')
+
+
+def test_simplify_not_apple_and_appleosx():
+ validate_simplify('NOT APPLE AND APPLE_OSX', 'OFF')
+
+
+def test_simplify_unix_and_bar_or_win32():
+ validate_simplify('WIN32 AND bar AND UNIX', 'OFF')
+
+
+def test_simplify_unix_or_bar_or_win32():
+ validate_simplify('WIN32 OR bar OR UNIX', 'ON')
+
+
+def test_simplify_complex_true():
+ validate_simplify('WIN32 OR ( APPLE OR UNIX)', 'ON')
+
+
+def test_simplify_apple_unix_freebsd():
+ validate_simplify('( APPLE OR ( UNIX OR FREEBSD ))', 'UNIX')
+
+
+def test_simplify_apple_unix_freebsd_foobar():
+ validate_simplify('( APPLE OR ( UNIX OR FREEBSD ) OR foobar)',
+ 'UNIX OR foobar')
+
+
+def test_simplify_complex_false():
+ validate_simplify('WIN32 AND foobar AND ( '
+ 'APPLE OR ( UNIX OR FREEBSD ))',
+ 'OFF')
+
+
+def test_simplify_android_not_apple():
+ validate_simplify('ANDROID AND NOT ANDROID_EMBEDDED AND NOT APPLE_OSX',
+ 'ANDROID AND NOT ANDROID_EMBEDDED')
diff --git a/util/cmake/tests/test_operations.py b/util/cmake/tests/test_operations.py
new file mode 100755
index 0000000000..c1e5f1b250
--- /dev/null
+++ b/util/cmake/tests/test_operations.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the plugins of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from pro2cmake import AddOperation, SetOperation, UniqueAddOperation, RemoveOperation
+
+def test_add_operation():
+ op = AddOperation(['bar', 'buz'])
+
+ result = op.process(['foo', 'bar'], ['foo', 'bar'], lambda x: x)
+ assert ['foo', 'bar', 'bar', 'buz'] == result
+
+
+def test_uniqueadd_operation():
+ op = UniqueAddOperation(['bar', 'buz'])
+
+ result = op.process(['foo', 'bar'], ['foo', 'bar'], lambda x: x)
+ assert ['foo', 'bar', 'buz'] == result
+
+
+def test_set_operation():
+ op = SetOperation(['bar', 'buz'])
+
+ result = op.process(['foo', 'bar'], ['foo', 'bar'], lambda x: x)
+ assert ['bar', 'buz'] == result
+
+
+def test_remove_operation():
+ op = RemoveOperation(['bar', 'buz'])
+
+ result = op.process(['foo', 'bar'], ['foo', 'bar'], lambda x: x)
+ assert ['foo', '-buz'] == result
diff --git a/util/cmake/tests/test_parsing.py b/util/cmake/tests/test_parsing.py
new file mode 100755
index 0000000000..f924b13913
--- /dev/null
+++ b/util/cmake/tests/test_parsing.py
@@ -0,0 +1,345 @@
+#!/usr/bin/env python3
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the plugins of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import os
+from pro2cmake import QmakeParser
+
+
+_tests_path = os.path.dirname(os.path.abspath(__file__))
+
+
+def validate_op(key, op, value, to_validate):
+ assert key == to_validate['key']
+ assert op == to_validate['operation']
+ assert value == to_validate.get('value', None)
+
+
+def validate_single_op(key, op, value, to_validate):
+ assert len(to_validate) == 1
+ validate_op(key, op, value, to_validate[0])
+
+
+def evaluate_condition(to_validate):
+ assert 'condition' in to_validate
+ assert 'statements' in to_validate
+
+ return (to_validate['condition'],
+ to_validate['statements'],
+ to_validate.get('else_statements', {}))
+
+
+def validate_default_else_test(file_name):
+ result = parse_file(file_name)
+ assert len(result) == 1
+
+ (cond, if_branch, else_branch) = evaluate_condition(result[0])
+ assert cond == 'qtConfig(timezone)'
+ validate_single_op('A', '=', ['1'], if_branch)
+
+ assert len(else_branch) == 1
+ (cond2, if2_branch, else2_branch) = evaluate_condition(else_branch[0])
+ assert cond2 == 'win32'
+ validate_single_op('B', '=', ['2'], if2_branch)
+ validate_single_op('C', '=', ['3'], else2_branch)
+
+
+def parse_file(file):
+ p = QmakeParser(debug=True)
+ result = p.parseFile(file)
+
+ print('\n\n#### Parser result:')
+ print(result)
+ print('\n#### End of parser result.\n')
+
+ print('\n\n####Parser result dictionary:')
+ print(result.asDict())
+ print('\n#### End of parser result dictionary.\n')
+
+ result_dictionary = result.asDict()
+
+ assert len(result_dictionary) == 1
+
+ return result_dictionary['statements']
+
+
+def test_else():
+ result = parse_file(_tests_path + '/data/else.pro')
+ assert len(result) == 1
+
+ (cond, if_branch, else_branch) = evaluate_condition(result[0])
+
+ assert cond == 'linux'
+ validate_single_op('SOURCES', '+=', ['a.cpp'], if_branch)
+ validate_single_op('SOURCES', '+=', ['b.cpp'], else_branch)
+
+
+def test_else2():
+ result = parse_file(_tests_path + '/data/else2.pro')
+ assert len(result) == 1
+
+ (cond, if_branch, else_branch) = evaluate_condition(result[0])
+ assert cond == 'osx'
+ validate_single_op('A', '=', ['1'], if_branch)
+
+ assert len(else_branch) == 1
+ (cond2, if2_branch, else2_branch) = evaluate_condition(else_branch[0])
+ assert cond2 == 'win32'
+ validate_single_op('B', '=', ['2'], if2_branch)
+
+ validate_single_op('C', '=', ['3'], else2_branch)
+
+
+def test_else3():
+ validate_default_else_test(_tests_path + '/data/else3.pro')
+
+
+def test_else4():
+ validate_default_else_test(_tests_path + '/data/else4.pro')
+
+
+def test_else5():
+ validate_default_else_test(_tests_path + '/data/else5.pro')
+
+
+def test_else6():
+ validate_default_else_test(_tests_path + '/data/else6.pro')
+
+
+def test_else7():
+ result = parse_file(_tests_path + '/data/else7.pro')
+ assert len(result) == 1
+
+
+def test_else8():
+ validate_default_else_test(_tests_path + '/data/else8.pro')
+
+
+def test_multiline_assign():
+ result = parse_file(_tests_path + '/data/multiline_assign.pro')
+ assert len(result) == 2
+ validate_op('A', '=', ['42', '43', '44'], result[0])
+ validate_op('B', '=', ['23'], result[1])
+
+
+def test_include():
+ result = parse_file(_tests_path + '/data/include.pro')
+ assert len(result) == 3
+ validate_op('A', '=', ['42'], result[0])
+ include = result[1]
+ assert len(include) == 1
+ assert include.get('included', '') == 'foo'
+ validate_op('B', '=', ['23'], result[2])
+
+
+def test_load():
+ result = parse_file(_tests_path + '/data/load.pro')
+ assert len(result) == 3
+ validate_op('A', '=', ['42'], result[0])
+ load = result[1]
+ assert len(load) == 1
+ assert load.get('loaded', '') == 'foo'
+ validate_op('B', '=', ['23'], result[2])
+
+
+def test_definetest():
+ result = parse_file(_tests_path + '/data/definetest.pro')
+ assert len(result) == 1
+ assert result[0] == []
+
+
+def test_for():
+ result = parse_file(_tests_path + '/data/for.pro')
+ assert len(result) == 2
+ validate_op('SOURCES', '=', ['main.cpp'], result[0])
+ assert result[1] == []
+
+
+def test_single_line_for():
+ result = parse_file(_tests_path + '/data/single_line_for.pro')
+ assert len(result) == 1
+ assert result[0] == []
+
+
+def test_unset():
+ result = parse_file(_tests_path + '/data/unset.pro')
+ assert len(result) == 1
+ assert result[0] == []
+
+
+def test_quoted():
+ result = parse_file(_tests_path + '/data/quoted.pro')
+ assert len(result) == 1
+
+
+def test_complex_values():
+ result = parse_file(_tests_path + '/data/complex_values.pro')
+ assert len(result) == 1
+
+
+def test_function_if():
+ result = parse_file(_tests_path + '/data/function_if.pro')
+ assert len(result) == 1
+
+
+def test_realworld_standardpaths():
+ result = parse_file(_tests_path + '/data/standardpaths.pro')
+
+ (cond, if_branch, else_branch) = evaluate_condition(result[0])
+ assert cond == 'win32'
+ assert len(if_branch) == 1
+ assert len(else_branch) == 1
+
+ # win32:
+ (cond1, if_branch1, else_branch1) = evaluate_condition(if_branch[0])
+ assert cond1 == '!winrt'
+ assert len(if_branch1) == 1
+ validate_op('SOURCES', '+=', ['io/qstandardpaths_win.cpp'], if_branch1[0])
+ assert len(else_branch1) == 1
+ validate_op('SOURCES', '+=', ['io/qstandardpaths_winrt.cpp'], else_branch1[0])
+
+ # unix:
+ (cond2, if_branch2, else_branch2) = evaluate_condition(else_branch[0])
+ assert cond2 == 'unix'
+ assert len(if_branch2) == 1
+ assert len(else_branch2) == 0
+
+ # mac / else:
+ (cond3, if_branch3, else_branch3) = evaluate_condition(if_branch2[0])
+ assert cond3 == 'mac'
+ assert len(if_branch3) == 1
+ validate_op('OBJECTIVE_SOURCES', '+=', ['io/qstandardpaths_mac.mm'], if_branch3[0])
+ assert len(else_branch3) == 1
+
+ # android / else:
+ (cond4, if_branch4, else_branch4) = evaluate_condition(else_branch3[0])
+ assert cond4 == 'android && !android-embedded'
+ assert len(if_branch4) == 1
+ validate_op('SOURCES', '+=', ['io/qstandardpaths_android.cpp'], if_branch4[0])
+ assert len(else_branch4) == 1
+
+ # haiku / else:
+ (cond5, if_branch5, else_branch5) = evaluate_condition(else_branch4[0])
+ assert cond5 == 'haiku'
+ assert len(if_branch5) == 1
+ validate_op('SOURCES', '+=', ['io/qstandardpaths_haiku.cpp'], if_branch5[0])
+ assert len(else_branch5) == 1
+ validate_op('SOURCES', '+=', ['io/qstandardpaths_unix.cpp'], else_branch5[0])
+
+
+def test_realworld_comment_scope():
+ result = parse_file(_tests_path + '/data/comment_scope.pro')
+ assert len(result) == 2
+ (cond, if_branch, else_branch) = evaluate_condition(result[0])
+ assert cond == 'freebsd|openbsd'
+ assert len(if_branch) == 1
+ validate_op('QMAKE_LFLAGS_NOUNDEF', '=', None, if_branch[0])
+
+ assert result[1].get('included', '') == 'animation/animation.pri'
+
+
+def test_realworld_contains_scope():
+ result = parse_file(_tests_path + '/data/contains_scope.pro')
+ assert len(result) == 2
+
+
+def test_realworld_complex_assign():
+ result = parse_file(_tests_path + '/data/complex_assign.pro')
+ assert len(result) == 1
+ validate_op('qmake-clean.commands', '+=', '( cd qmake && $(MAKE) clean ":-(==)-:" \'(Foo)\' )'.split(),
+ result[0])
+
+
+def test_realworld_complex_condition():
+ result = parse_file(_tests_path + '/data/complex_condition.pro')
+ assert len(result) == 1
+ (cond, if_branch, else_branch) = evaluate_condition(result[0])
+ assert cond == '!system("dbus-send --session --type=signal / ' \
+ 'local.AutotestCheck.Hello >$$QMAKE_SYSTEM_NULL_DEVICE ' \
+ '2>&1")'
+ assert len(if_branch) == 1
+ validate_op('SOURCES', '=', ['dbus.cpp'], if_branch[0])
+
+ assert len(else_branch) == 0
+
+
+def test_realworld_sql():
+ result = parse_file(_tests_path + '/data/sql.pro')
+ assert len(result) == 2
+ validate_op('TEMPLATE', '=', ['subdirs'], result[0])
+ validate_op('SUBDIRS', '=', ['kernel'], result[1])
+
+
+def test_realworld_qtconfig():
+ result = parse_file(_tests_path + '/data/escaped_value.pro')
+ assert len(result) == 1
+ validate_op('MODULE_AUX_INCLUDES', '=', ['\\$\\$QT_MODULE_INCLUDE_BASE/QtANGLE'], result[0])
+
+
+def test_realworld_lc():
+ result = parse_file(_tests_path + '/data/lc.pro')
+ assert len(result) == 3
+
+
+def test_realworld_lc_with_comment_in_between():
+ result = parse_file(_tests_path + '/data/lc_with_comment.pro')
+
+ my_var = result[1]['value'][0]
+ assert my_var == 'foo'
+
+ my_var = result[2]['value'][0]
+ assert my_var == 'foo2'
+
+ my_var = result[3]['value'][0]
+ assert my_var == 'foo3'
+
+ my_var = result[4]['value'][0]
+ assert my_var == 'foo4'
+
+ my_var = result[5]['value'][0]
+ assert my_var == 'foo5'
+
+ sub_dirs = result[0]['value']
+ assert sub_dirs[0] == 'tga'
+ assert sub_dirs[1] == 'wbmp'
+ assert len(result) == 6
+
+
+def test_condition_without_scope():
+ result = parse_file(_tests_path + '/data/condition_without_scope.pro')
+ assert len(result) == 1
+
+
+def test_multi_condition_divided_by_lc():
+ result = parse_file(_tests_path + '/data/multi_condition_divided_by_lc.pro')
+ assert len(result) == 1
+
+
+def test_nested_function_calls():
+ result = parse_file(_tests_path + '/data/nested_function_calls.pro')
+ assert len(result) == 1
diff --git a/util/cmake/tests/test_scope_handling.py b/util/cmake/tests/test_scope_handling.py
new file mode 100755
index 0000000000..c0b553fabd
--- /dev/null
+++ b/util/cmake/tests/test_scope_handling.py
@@ -0,0 +1,338 @@
+#!/usr/bin/env python3
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the plugins of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from pro2cmake import Scope, SetOperation, merge_scopes, recursive_evaluate_scope
+
+import pytest
+import typing
+
+ScopeList = typing.List[Scope]
+
+def _map_to_operation(**kwargs):
+ result = {} # type: typing.Mapping[str, typing.List[SetOperation]]
+ for (key, value) in kwargs.items():
+ result[key] = [SetOperation([value])]
+ return result
+
+
+def _new_scope(*, parent_scope=None, condition='', **kwargs) -> Scope:
+ return Scope(parent_scope=parent_scope,
+ file='file1', condition=condition, operations=_map_to_operation(**kwargs))
+
+
+def _evaluate_scopes(scopes: ScopeList) -> ScopeList:
+ for s in scopes:
+ if not s.parent:
+ recursive_evaluate_scope(s)
+ return scopes
+
+
+def _validate(input_scopes: ScopeList, output_scopes: ScopeList):
+ merged_scopes = merge_scopes(input_scopes)
+ assert merged_scopes == output_scopes
+
+
+def test_evaluate_one_scope():
+ scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
+
+ input_scope = scope
+ recursive_evaluate_scope(scope)
+ assert scope == input_scope
+
+
+def test_evaluate_child_scope():
+ scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
+ _new_scope(parent_scope=scope, condition='QT_FEATURE_bar', test2='bar')
+
+ input_scope = scope
+ recursive_evaluate_scope(scope)
+
+ assert scope.total_condition == 'QT_FEATURE_foo'
+ assert len(scope.children) == 1
+ assert scope.get_string('test1') == 'bar'
+ assert scope.get_string('test2', 'not found') == 'not found'
+
+ child = scope.children[0]
+ assert child.total_condition == 'QT_FEATURE_bar AND QT_FEATURE_foo'
+ assert child.get_string('test1', 'not found') == 'not found'
+ assert child.get_string('test2') == 'bar'
+
+
+def test_evaluate_two_child_scopes():
+ scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
+ _new_scope(parent_scope=scope, condition='QT_FEATURE_bar', test2='bar')
+ _new_scope(parent_scope=scope, condition='QT_FEATURE_buz', test3='buz')
+
+ input_scope = scope
+ recursive_evaluate_scope(scope)
+
+ assert scope.total_condition == 'QT_FEATURE_foo'
+ assert len(scope.children) == 2
+ assert scope.get_string('test1') == 'bar'
+ assert scope.get_string('test2', 'not found') == 'not found'
+ assert scope.get_string('test3', 'not found') == 'not found'
+
+ child1 = scope.children[0]
+ assert child1.total_condition == 'QT_FEATURE_bar AND QT_FEATURE_foo'
+ assert child1.get_string('test1', 'not found') == 'not found'
+ assert child1.get_string('test2') == 'bar'
+ assert child1.get_string('test3', 'not found') == 'not found'
+
+ child2 = scope.children[1]
+ assert child2.total_condition == 'QT_FEATURE_buz AND QT_FEATURE_foo'
+ assert child2.get_string('test1', 'not found') == 'not found'
+ assert child2.get_string('test2') == ''
+ assert child2.get_string('test3', 'not found') == 'buz'
+
+
+def test_evaluate_else_child_scopes():
+ scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
+ _new_scope(parent_scope=scope, condition='QT_FEATURE_bar', test2='bar')
+ _new_scope(parent_scope=scope, condition='else', test3='buz')
+
+ input_scope = scope
+ recursive_evaluate_scope(scope)
+
+ assert scope.total_condition == 'QT_FEATURE_foo'
+ assert len(scope.children) == 2
+ assert scope.get_string('test1') == 'bar'
+ assert scope.get_string('test2', 'not found') == 'not found'
+ assert scope.get_string('test3', 'not found') == 'not found'
+
+ child1 = scope.children[0]
+ assert child1.total_condition == 'QT_FEATURE_bar AND QT_FEATURE_foo'
+ assert child1.get_string('test1', 'not found') == 'not found'
+ assert child1.get_string('test2') == 'bar'
+ assert child1.get_string('test3', 'not found') == 'not found'
+
+ child2 = scope.children[1]
+ assert child2.total_condition == 'QT_FEATURE_foo AND NOT QT_FEATURE_bar'
+ assert child2.get_string('test1', 'not found') == 'not found'
+ assert child2.get_string('test2') == ''
+ assert child2.get_string('test3', 'not found') == 'buz'
+
+
+def test_evaluate_invalid_else_child_scopes():
+ scope = _new_scope(condition='QT_FEATURE_foo', test1='bar')
+ _new_scope(parent_scope=scope, condition='else', test3='buz')
+ _new_scope(parent_scope=scope, condition='QT_FEATURE_bar', test2='bar')
+
+ input_scope = scope
+ with pytest.raises(AssertionError):
+ recursive_evaluate_scope(scope)
+
+
+def test_merge_empty_scope_list():
+ _validate([], [])
+
+
+def test_merge_one_scope():
+ scopes = [_new_scope(test='foo')]
+
+ recursive_evaluate_scope(scopes[0])
+
+ _validate(scopes, scopes)
+
+
+def test_merge_one_on_scope():
+ scopes = [_new_scope(condition='ON', test='foo')]
+
+ recursive_evaluate_scope(scopes[0])
+
+ _validate(scopes, scopes)
+
+
+def test_merge_one_off_scope():
+ scopes = [_new_scope(condition='OFF', test='foo')]
+
+ recursive_evaluate_scope(scopes[0])
+
+ _validate(scopes, [])
+
+
+def test_merge_one_conditioned_scope():
+ scopes = [_new_scope(condition='QT_FEATURE_foo', test='foo')]
+
+ recursive_evaluate_scope(scopes[0])
+
+ _validate(scopes, scopes)
+
+
+def test_merge_two_scopes_with_same_condition():
+ scopes = [_new_scope(condition='QT_FEATURE_bar', test='foo'),
+ _new_scope(condition='QT_FEATURE_bar', test2='bar')]
+
+ recursive_evaluate_scope(scopes[0])
+ recursive_evaluate_scope(scopes[1])
+
+ result = merge_scopes(scopes)
+
+ assert len(result) == 1
+ r0 = result[0]
+ assert r0.total_condition == 'QT_FEATURE_bar'
+ assert r0.get_string('test') == 'foo'
+ assert r0.get_string('test2') == 'bar'
+
+
+def test_merge_three_scopes_two_with_same_condition():
+ scopes = [_new_scope(condition='QT_FEATURE_bar', test='foo'),
+ _new_scope(condition='QT_FEATURE_baz', test1='buz'),
+ _new_scope(condition='QT_FEATURE_bar', test2='bar')]
+
+ recursive_evaluate_scope(scopes[0])
+ recursive_evaluate_scope(scopes[1])
+ recursive_evaluate_scope(scopes[2])
+
+ result = merge_scopes(scopes)
+
+ assert len(result) == 2
+ r0 = result[0]
+ assert r0.total_condition == 'QT_FEATURE_bar'
+ assert r0.get_string('test') == 'foo'
+ assert r0.get_string('test2') == 'bar'
+
+ assert result[1] == scopes[1]
+
+
+def test_merge_two_unrelated_on_off_scopes():
+ scopes = [_new_scope(condition='ON', test='foo'),
+ _new_scope(condition='OFF', test2='bar')]
+
+ recursive_evaluate_scope(scopes[0])
+ recursive_evaluate_scope(scopes[1])
+
+ _validate(scopes, [scopes[0]])
+
+
+def test_merge_two_unrelated_on_off_scopes():
+ scopes = [_new_scope(condition='OFF', test='foo'),
+ _new_scope(condition='ON', test2='bar')]
+
+ recursive_evaluate_scope(scopes[0])
+ recursive_evaluate_scope(scopes[1])
+
+ _validate(scopes, [scopes[1]])
+
+
+def test_merge_parent_child_scopes_with_different_conditions():
+ scope = _new_scope(condition='FOO', test1='parent')
+ scopes = [scope, _new_scope(parent_scope=scope, condition='bar', test2='child')]
+
+ recursive_evaluate_scope(scope)
+
+ _validate(scopes, scopes)
+
+
+def test_merge_parent_child_scopes_with_same_conditions():
+ scope = _new_scope(condition='FOO AND bar', test1='parent')
+ scopes = [scope, _new_scope(parent_scope=scope, condition='FOO AND bar', test2='child')]
+
+ recursive_evaluate_scope(scope)
+
+ result = merge_scopes(scopes)
+
+ assert len(result) == 1
+ r0 = result[0]
+ assert r0.parent == None
+ assert r0.total_condition == 'FOO AND bar'
+ assert r0.get_string('test1') == 'parent'
+ assert r0.get_string('test2') == 'child'
+
+
+def test_merge_parent_child_scopes_with_on_child_condition():
+ scope = _new_scope(condition='FOO AND bar', test1='parent')
+ scopes = [scope, _new_scope(parent_scope=scope, condition='ON', test2='child')]
+
+ recursive_evaluate_scope(scope)
+
+ result = merge_scopes(scopes)
+
+ assert len(result) == 1
+ r0 = result[0]
+ assert r0.parent == None
+ assert r0.total_condition == 'FOO AND bar'
+ assert r0.get_string('test1') == 'parent'
+ assert r0.get_string('test2') == 'child'
+
+
+# Real world examples:
+
+# qstandardpaths selection:
+
+def test_qstandardpaths_scopes():
+ # top level:
+ scope1 = _new_scope(condition='ON', scope_id=1)
+
+ # win32 {
+ scope2 = _new_scope(parent_scope=scope1, condition='WIN32')
+ # !winrt {
+ # SOURCES += io/qstandardpaths_win.cpp
+ scope3 = _new_scope(parent_scope=scope2, condition='NOT WINRT',
+ SOURCES='qsp_win.cpp')
+ # } else {
+ # SOURCES += io/qstandardpaths_winrt.cpp
+ scope4 = _new_scope(parent_scope=scope2, condition='else',
+ SOURCES='qsp_winrt.cpp')
+ # }
+ # else: unix {
+ scope5 = _new_scope(parent_scope=scope1, condition='else')
+ scope6 = _new_scope(parent_scope=scope5, condition='UNIX')
+ # mac {
+ # OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm
+ scope7 = _new_scope(parent_scope=scope6, condition='APPLE_OSX', SOURCES='qsp_mac.mm')
+ # } else:android:!android-embedded {
+ # SOURCES += io/qstandardpaths_android.cpp
+ scope8 = _new_scope(parent_scope=scope6, condition='else')
+ scope9 = _new_scope(parent_scope=scope8,
+ condition='ANDROID AND NOT ANDROID_EMBEDDED',
+ SOURCES='qsp_android.cpp')
+ # } else:haiku {
+ # SOURCES += io/qstandardpaths_haiku.cpp
+ scope10 = _new_scope(parent_scope=scope8, condition='else')
+ scope11 = _new_scope(parent_scope=scope10, condition='HAIKU', SOURCES='qsp_haiku.cpp')
+ # } else {
+ # SOURCES +=io/qstandardpaths_unix.cpp
+ scope12 = _new_scope(parent_scope=scope10, condition='else', SOURCES='qsp_unix.cpp')
+ # }
+ # }
+
+ recursive_evaluate_scope(scope1)
+
+ assert scope1.total_condition == 'ON'
+ assert scope2.total_condition == 'WIN32'
+ assert scope3.total_condition == 'WIN32 AND NOT WINRT'
+ assert scope4.total_condition == 'WINRT'
+ assert scope5.total_condition == 'UNIX'
+ assert scope6.total_condition == 'UNIX'
+ assert scope7.total_condition == 'APPLE_OSX'
+ assert scope8.total_condition == 'UNIX AND NOT APPLE_OSX'
+ assert scope9.total_condition == 'ANDROID AND NOT ANDROID_EMBEDDED'
+ assert scope10.total_condition == 'UNIX AND NOT APPLE_OSX AND (ANDROID_EMBEDDED OR NOT ANDROID)'
+ assert scope11.total_condition == 'HAIKU AND (ANDROID_EMBEDDED OR NOT ANDROID)'
+ assert scope12.total_condition == 'UNIX AND NOT APPLE_OSX AND NOT HAIKU AND (ANDROID_EMBEDDED OR NOT ANDROID)'