# Copyright (C) 2016 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 source("../../shared/qtcreator.py") def main(): startQC() if not startedWithoutPluginError(): return # using a temporary directory won't mess up a potentially existing workingDir = tempDir() projectName = createNewQtQuickApplication(workingDir)[1] editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget") if placeCursorToLine(editor, "}"): type(editor, '') type(editor, '') type(editor, '') type(editor, '') typeLines(editor, ['Timer {', 'property int runCount: 0', 'interval: 2000', 'repeat: true', 'running: runCount < 2', 'onTriggered: {', 'runCount += 1;', 'var i;', 'for (i = 1; i < 2500; ++i) {', 'var j = i * i;', 'console.log(j);']) invokeMenuItem("File", "Save All") availableConfigs = iterateBuildConfigs("Debug") if not availableConfigs: test.fatal("Haven't found a suitable Qt version (need Qt 6.2+) - leaving without profiling.") else: performTest(workingDir, projectName, availableConfigs) invokeMenuItem("File", "Exit") def performTest(workingDir, projectName, availableConfigs): def __elapsedTime__(elapsedTimeLabelText): return float(re.search("Elapsed:\s+(-?\d+\.\d+) s", elapsedTimeLabelText).group(1)) for kit, config in availableConfigs: # switching from MSVC to MinGW build will fail on the clean step of 'Rebuild All Projects' # because of differences between MSVC's and MinGW's Makefile (so clean before changing kit) selectFromLocator("t clean", "Clean Project") verifyBuildConfig(kit, config, True, True, True) test.log("Selected kit '%s'" % Targets.getStringForTarget(kit)) # explicitly build before start debugging for adding the executable as allowed program to WinFW selectFromLocator("t rebuild", "Rebuild All Projects") waitForCompile() if not checkCompile(): test.fatal("Compile had errors... Skipping current build config") continue switchViewTo(ViewConstants.DEBUG) selectFromCombo(":Analyzer Toolbar.AnalyzerManagerToolBox_QComboBox", "QML Profiler") recordButton = waitForObject("{container=':DebugModeWidget.Toolbar_QDockWidget' " "type='QToolButton' unnamed='1' visible='1' " "toolTip?='*able Profiling'}") if not test.verify(recordButton.checked, "Verifying recording is enabled."): test.log("Enabling recording for the test run") clickButton(recordButton) startButton = waitForObject(":Analyzer Toolbar.Start_QToolButton") clickButton(startButton) stopButton = waitForObject(":Qt Creator.Stop_QToolButton") elapsedLabel = waitForObject(":Analyzer Toolbar.Elapsed:_QLabel", 3000) waitFor('"Elapsed: 8" in str(elapsedLabel.text)', 20000) clickButton(stopButton) test.verify(waitFor("not stopButton.enabled", 5000), "stopButton should be disabled") test.verify(waitFor("startButton.enabled", 2000), "startButton should be enabled") try: test.verify(waitFor("__elapsedTime__(str(elapsedLabel.text)) > 0", 2000), "Elapsed time should be positive in string '%s'" % str(elapsedLabel.text)) except: test.fatal("Could not read elapsed time from '%s'" % str(elapsedLabel.text)) if safeClickTab("Statistics"): (colPercent, colTotal, colSelfPercent, colSelf, colCalls, colMean, colMedian, colLongest, colShortest) = range(2, 11) model = waitForObject(":Events.QmlProfilerEventsTable_QmlProfiler::" "Internal::QmlProfilerStatisticsMainView").model() compareEventsTab(model, "events_qt6.2.4.tsv") test.compare(dumpItems(model, column=colPercent)[0], '100 %') # cannot run following test on colShortest (unstable) for i in [colMean, colMedian, colLongest]: for item in dumpItems(model, column=i)[2:5]: test.verify(item.endswith('ms'), "Verify that '%s' ends with 'ms'" % item) for i in [colTotal, colMean, colMedian, colLongest, colShortest]: for item in dumpItems(model, column=i): test.verify(not item.startswith('0.000 '), "Check for implausible durations (QTCREATORBUG-8996): %s" % item) for row in range(model.rowCount()): selfPercent = str(model.index(row, colSelfPercent).data()) totalPercent = str(model.index(row, colPercent).data()) test.verify(float(selfPercent[:-2]) <= float(totalPercent[:-2]), "Self percentage (%s) can't be more than total percentage (%s)" % (selfPercent, totalPercent)) if str(model.index(row, colCalls).data()) == "1": for col in [colMedian, colLongest, colShortest]: test.compare(str(model.index(row, colMean).data()), str(model.index(row, col).data()), "For just one call, no differences in execution time may be shown.") elif str(model.index(row, colCalls).data()) == "2": test.compare(str(model.index(row, colMedian).data()), str(model.index(row, colMean).data()), "For two calls, median and mean time must be the same.") progressBarWait(15000, False) # wait for "Build" progressbar to disappear clickButton(waitForObject(":Analyzer Toolbar.Clear_QToolButton")) test.verify(waitFor("model.rowCount() == 0", 3000), "Analyzer results cleared.") def compareEventsTab(model, file): significantColumns = [0, 1, 6, 11] expectedTable = [] for record in testData.dataset(file): expectedTable.append([testData.field(record, str(col)) for col in significantColumns]) foundTable = [] for row in range(model.rowCount()): foundTable.append([str(model.index(row, col).data()) for col in significantColumns]) test.compare(model.rowCount(), len(expectedTable), "Checking number of rows in Events table") if not test.verify(containsOnce(expectedTable, foundTable), "Verifying that Events table matches expected values"): test.log("Events displayed by Creator: %s" % foundTable, str(expectedTable)) def containsOnce(tuple, items): for item in items: if tuple.count(item) != 1: return False return True def safeClickTab(tab): for bar in [":Qt Creator.Events_QTabBar", ":Qt Creator.Timeline_QTabBar"]: try: clickOnTab(bar, tab, 1000) return True except: pass test.fatal("Tab %s is not being shown." % tab) return False