summaryrefslogtreecommitdiffstats
path: root/tests/auto/concurrent/qtconcurrentfiltermapgenerated/generator/generate_testcase.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/concurrent/qtconcurrentfiltermapgenerated/generator/generate_testcase.py')
-rw-r--r--tests/auto/concurrent/qtconcurrentfiltermapgenerated/generator/generate_testcase.py366
1 files changed, 366 insertions, 0 deletions
diff --git a/tests/auto/concurrent/qtconcurrentfiltermapgenerated/generator/generate_testcase.py b/tests/auto/concurrent/qtconcurrentfiltermapgenerated/generator/generate_testcase.py
new file mode 100644
index 0000000000..d35a7e9065
--- /dev/null
+++ b/tests/auto/concurrent/qtconcurrentfiltermapgenerated/generator/generate_testcase.py
@@ -0,0 +1,366 @@
+# Copyright (C) 2020 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+import textwrap
+import time
+from subprocess import Popen, PIPE
+
+from function_signature import build_function_signature, build_function_name
+from option_management import need_separate_output_sequence, qt_quirk_case
+
+
+def InputSequenceItem(toptions):
+ if toptions["inputitemtype"] == "standard":
+ return "SequenceItem<tag_input>"
+ if toptions["inputitemtype"] == "noconstruct":
+ return "NoConstructSequenceItem<tag_input>"
+ if toptions["inputitemtype"] == "moveonly":
+ return "MoveOnlySequenceItem<tag_input>"
+ if toptions["inputitemtype"] == "moveonlynoconstruct":
+ return "MoveOnlyNoConstructSequenceItem<tag_input>"
+ assert False
+
+
+def InputSequence(toptions):
+ item = InputSequenceItem(toptions)
+ if toptions["inputsequence"] == "standard":
+ return "std::vector<{}>".format(item)
+ if toptions["inputsequence"] == "moveonly":
+ return "MoveOnlyVector<{}>".format(item)
+ assert False
+
+
+def InputSequenceInitializationString(toptions):
+ t = InputSequenceItem(toptions)
+ # construct IILE
+ mystring = ("[](){" + InputSequence(toptions) + " result;\n"
+ + "\n".join("result.push_back({}({}, true));".format(t, i) for i in range(1, 7))
+ + "\n return result; }()")
+ return mystring
+
+
+def OutputSequenceItem(toptions):
+ if toptions["map"] and (toptions["inplace"] or toptions["maptype"] == "same"):
+ return InputSequenceItem(toptions)
+
+ if toptions["map"]:
+ if toptions["mappeditemtype"] == "standard":
+ return "SequenceItem<tag_mapped>"
+ if toptions["mappeditemtype"] == "noconstruct":
+ return "NoConstructSequenceItem<tag_mapped>"
+ if toptions["mappeditemtype"] == "moveonly":
+ return "MoveOnlySequenceItem<tag_mapped>"
+ if toptions["mappeditemtype"] == "moveonlynoconstruct":
+ return "MoveOnlyNoConstructSequenceItem<tag_mapped>"
+ assert(False)
+ else:
+ return InputSequenceItem(toptions)
+
+
+def ReducedItem(toptions):
+ if toptions["reductiontype"] == "same":
+ return OutputSequenceItem(toptions)
+ else:
+ if toptions["reductionitemtype"] == "standard":
+ return "SequenceItem<tag_reduction>"
+ if toptions["reductionitemtype"] == "noconstruct":
+ return "NoConstructSequenceItem<tag_reduction>"
+ if toptions["reductionitemtype"] == "moveonly":
+ return "MoveOnlySequenceItem<tag_reduction>"
+ if toptions["reductionitemtype"] == "moveonlynoconstruct":
+ return "MoveOnlyNoConstructSequenceItem<tag_reduction>"
+ assert(False)
+
+
+def OutputSequence(toptions):
+ item = OutputSequenceItem(toptions)
+ # quirk of qt: not a QFuture<Sequence> is returned
+ if qt_quirk_case(toptions):
+ return "QList<{}>".format(item)
+
+ needs_extra = need_separate_output_sequence(toptions)
+ if not needs_extra:
+ return InputSequence(toptions)
+
+
+ if toptions["outputsequence"] == "standard":
+ return "std::vector<{}>".format(item)
+ if toptions["outputsequence"] == "moveonly":
+ return "MoveOnlyVector<{}>".format(item)
+ assert False
+
+
+def resultData(toptions):
+ result = [1, 2, 3, 4, 5, 6]
+ if toptions["filter"]:
+ result = filter(lambda x: x % 2 == 1, result)
+ if toptions["map"]:
+ result = map(lambda x: 2 * x, result)
+ if toptions["reduce"]:
+ result = sum(result)
+ return result
+
+
+def OutputSequenceInitializationString(toptions):
+ t = OutputSequenceItem(toptions)
+ # construct IILE
+ mystring = ("[](){" + OutputSequence(toptions) + " result;\n"
+ + "\n".join("result.push_back({}({}, true));".format(t, i) for i in resultData(toptions))
+ + "\n return result; }()")
+ return mystring
+
+
+def OutputScalarInitializationString(toptions):
+ result = resultData(toptions)
+ assert isinstance(result, int)
+ return ReducedItem(toptions) + "(" + str(result) + ", true)"
+
+
+def FilterInitializationString(toptions):
+ item = InputSequenceItem(toptions)
+ if toptions["filterfunction"] == "function":
+ return "myfilter<{}>".format(item)
+ if toptions["filterfunction"] == "functor":
+ return "MyFilter<{}>{{}}".format(item)
+ if toptions["filterfunction"] == "memberfunction":
+ return "&{}::isOdd".format(item)
+ if toptions["filterfunction"] == "lambda":
+ return "[](const {}& x){{ return myfilter<{}>(x); }}".format(item, item)
+ if toptions["filterfunction"] == "moveonlyfunctor":
+ return "MyMoveOnlyFilter<{}>{{}}".format(item)
+ assert False
+
+
+def MapInitializationString(toptions):
+ oldtype = InputSequenceItem(toptions)
+ newtype = OutputSequenceItem(toptions)
+ if toptions["inplace"]:
+ assert oldtype == newtype
+ if toptions["mapfunction"] == "function":
+ return "myInplaceMap<{}>".format(oldtype)
+ if toptions["mapfunction"] == "functor":
+ return "MyInplaceMap<{}>{{}}".format(oldtype)
+ if toptions["mapfunction"] == "memberfunction":
+ return "&{}::multiplyByTwo".format(oldtype)
+ if toptions["mapfunction"] == "lambda":
+ return "[]({}& x){{ return myInplaceMap<{}>(x); }}".format(oldtype, oldtype)
+ if toptions["mapfunction"] == "moveonlyfunctor":
+ return "MyMoveOnlyInplaceMap<{}>{{}}".format(oldtype)
+ assert False
+ else:
+ if toptions["mapfunction"] == "function":
+ return "myMap<{f},{t}>".format(f=oldtype, t=newtype)
+ if toptions["mapfunction"] == "functor":
+ return "MyMap<{f},{t}>{{}}".format(f=oldtype, t=newtype)
+ if toptions["mapfunction"] == "memberfunction":
+ return "&{}::multiplyByTwo".format(newtype)
+ if toptions["mapfunction"] == "lambda":
+ return "[](const {f}& x){{ return myMap<{f},{t}>(x); }}".format(f=oldtype, t=newtype)
+ if toptions["mapfunction"] == "moveonlyfunctor":
+ return "MyMoveOnlyMap<{f},{t}>{{}}".format(f=oldtype, t=newtype)
+ assert False
+
+
+def ReductionInitializationString(toptions):
+ elementtype = OutputSequenceItem(toptions)
+ sumtype = ReducedItem(toptions)
+
+ if toptions["reductionfunction"] == "function":
+ return "myReduce<{f},{t}>".format(f=elementtype, t=sumtype)
+ if toptions["reductionfunction"] == "functor":
+ return "MyReduce<{f},{t}>{{}}".format(f=elementtype, t=sumtype)
+ if toptions["reductionfunction"] == "lambda":
+ return "[]({t}& sum, const {f}& x){{ return myReduce<{f},{t}>(sum, x); }}".format(f=elementtype, t=sumtype)
+ if toptions["reductionfunction"] == "moveonlyfunctor":
+ return "MyMoveOnlyReduce<{f},{t}>{{}}".format(f=elementtype, t=sumtype)
+ assert False
+
+
+def ReductionInitialvalueInitializationString(options):
+ return ReducedItem(options) + "(0, true)"
+
+
+def function_template_args(options):
+ args = []
+ out_s = OutputSequence(options)
+ in_s = InputSequence(options)
+ if options["reduce"] and options["reductionfunction"] == "lambda":
+ args.append(ReducedItem(options))
+ elif out_s != in_s:
+ if not qt_quirk_case(options):
+ args.append(out_s)
+
+ if len(args):
+ return "<" + ", ".join(args) + ">"
+
+ return ""
+
+
+numcall = 0
+
+
+def generate_testcase(function_options, testcase_options):
+ options = {**function_options, **testcase_options}
+
+ option_description = "\n".join(" {}={}".format(
+ a, b) for a, b in testcase_options.items())
+ option_description = textwrap.indent(option_description, " "*12)
+ function_signature = textwrap.indent(build_function_signature(function_options), " "*12)
+ testcase_name = "_".join("{}_{}".format(x, y) for x, y in options.items())
+ global numcall
+ numcall += 1
+ testcase_name = "test" + str(numcall)
+ function_name = build_function_name(options)
+
+ arguments = []
+
+ template_args = function_template_args(options)
+
+ # care about the thread pool
+ if options["pool"]:
+ pool_initialization = """QThreadPool pool;
+ pool.setMaxThreadCount(1);"""
+ arguments.append("&pool")
+ else:
+ pool_initialization = ""
+
+ # care about the input sequence
+ input_sequence_initialization_string = InputSequenceInitializationString(options)
+
+ if "inputsequencepassing" in options and options["inputsequencepassing"] == "lvalue" or options["inplace"]:
+ input_sequence_initialization = "auto input_sequence = " + \
+ input_sequence_initialization_string + ";"
+ arguments.append("input_sequence")
+ elif "inputsequencepassing" in options and options["inputsequencepassing"] == "rvalue":
+ input_sequence_initialization = ""
+ arguments.append(input_sequence_initialization_string)
+ else:
+ input_sequence_initialization = "auto input_sequence = " + \
+ input_sequence_initialization_string + ";"
+ arguments.append("input_sequence.begin()")
+ arguments.append("input_sequence.end()")
+
+ # care about the map:
+ if options["map"]:
+ map_initialization_string = MapInitializationString(options)
+ if options["mapfunctionpassing"] == "lvalue":
+ map_initialization = "auto map = " + map_initialization_string + ";"
+ arguments.append("map")
+ elif options["mapfunctionpassing"] == "rvalue":
+ map_initialization = ""
+ arguments.append(map_initialization_string)
+ else:
+ assert False
+ else:
+ map_initialization = ""
+
+ # care about the filter
+ if options["filter"]:
+ filter_initialization_string = FilterInitializationString(options)
+ if options["filterfunctionpassing"] == "lvalue":
+ filter_initialization = "auto filter = " + filter_initialization_string + ";"
+ arguments.append("filter")
+ elif options["filterfunctionpassing"] == "rvalue":
+ filter_initialization = ""
+ arguments.append(filter_initialization_string)
+ else:
+ assert (False)
+ else:
+ filter_initialization = ""
+
+ reduction_initialvalue_initialization = ""
+ # care about reduction
+ if options["reduce"]:
+ reduction_initialization_expression = ReductionInitializationString(options)
+ if options["reductionfunctionpassing"] == "lvalue":
+ reduction_initialization = "auto reductor = " + reduction_initialization_expression + ";"
+ arguments.append("reductor")
+ elif options["reductionfunctionpassing"] == "rvalue":
+ reduction_initialization = ""
+ arguments.append(reduction_initialization_expression)
+ else:
+ assert (False)
+
+ # initialvalue:
+ if options["initialvalue"]:
+ reduction_initialvalue_initialization_expression = ReductionInitialvalueInitializationString(options)
+ if options["reductioninitialvaluepassing"] == "lvalue":
+ reduction_initialvalue_initialization = "auto initialvalue = " + reduction_initialvalue_initialization_expression + ";"
+ arguments.append("initialvalue")
+ elif options["reductioninitialvaluepassing"] == "rvalue":
+ reduction_initialvalue_initialization = ""
+ arguments.append(reduction_initialvalue_initialization_expression)
+ else:
+ assert (False)
+
+ if options["reductionoptions"] == "UnorderedReduce":
+ arguments.append("QtConcurrent::UnorderedReduce")
+ elif options["reductionoptions"] == "OrderedReduce":
+ arguments.append("QtConcurrent::OrderedReduce")
+ elif options["reductionoptions"] == "SequentialReduce":
+ arguments.append("QtConcurrent::SequentialReduce")
+ else:
+ assert options["reductionoptions"] == "unspecified"
+ else:
+ reduction_initialization = ""
+
+ # what is the expected result
+ if options["filter"]:
+ if not options["reduce"]:
+ expected_result_expression = OutputSequenceInitializationString(options)
+ else:
+ expected_result_expression = OutputScalarInitializationString(options)
+ elif options["map"]:
+ if not options["reduce"]:
+ expected_result_expression = OutputSequenceInitializationString(options)
+ else:
+ expected_result_expression = OutputScalarInitializationString(options)
+
+ wait_result_expression = ""
+ if options["inplace"]:
+ if options["blocking"]:
+ result_accepting = ""
+ result_variable = "input_sequence"
+ else:
+ result_accepting = "auto future = "
+ result_variable = "input_sequence"
+ wait_result_expression = "future.waitForFinished();"
+ elif options["blocking"]:
+ result_accepting = "auto result = "
+ result_variable = "result"
+ else:
+ if not options["reduce"]:
+ result_accepting = "auto result = "
+ result_variable = "result.results()"
+ else:
+ result_accepting = "auto result = "
+ result_variable = "result.takeResult()"
+
+ arguments_passing = ", ".join(arguments)
+ final_string = f"""
+ void tst_QtConcurrentFilterMapGenerated::{testcase_name}()
+ {{
+ /* test for
+{function_signature}
+
+ with
+{option_description}
+ */
+
+ {pool_initialization}
+ {input_sequence_initialization}
+ {filter_initialization}
+ {map_initialization}
+ {reduction_initialization}
+ {reduction_initialvalue_initialization}
+
+ {result_accepting}QtConcurrent::{function_name}{template_args}({arguments_passing});
+
+ auto expected_result = {expected_result_expression};
+ {wait_result_expression}
+ QCOMPARE({result_variable}, expected_result);
+ }}
+ """
+ p = Popen(["clang-format"], stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ final_string = p.communicate(final_string.encode())[0].decode()
+
+ return (f" void {testcase_name}();\n", final_string)