test.py 8.67 KB
Newer Older
1 2
#############################################################################
##
3
## Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
## Contact: http://www.qt-project.org/legal
##
## This file is part of Qt Creator.
##
## 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 Digia.  For licensing terms and
## conditions see http://qt.digia.com/licensing.  For further information
## use the contact form at http://qt.digia.com/contact-us.
##
## 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, Digia gives you certain additional
## rights.  These rights are described in the Digia Qt LGPL Exception
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
##
#############################################################################

30 31 32
source("../../shared/qtcreator.py")

def main():
33 34 35
    if isQt4Build:
        test.log("QML Profiler is only available if Creator was built on Qt 5")
        return
36
    startApplication("qtcreator" + SettingsPath)
37 38
    if not startedWithoutPluginError():
        return
39 40
    # using a temporary directory won't mess up a potentially existing
    workingDir = tempDir()
41 42 43
    # we need a Qt >= 4.8
    analyzerTargets = Targets.desktopTargetClasses() ^ Targets.DESKTOP_474_GCC
    checkedTargets, projectName = createNewQtQuickApplication(workingDir, targets=analyzerTargets)
44 45 46 47 48
    editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
    if placeCursorToLine(editor, "MouseArea.*", True):
        type(editor, '<Up>')
        type(editor, '<Return>')
        typeLines(editor, ['Timer {',
49
                           'property int runCount: 0',
50 51
                           'interval: 2000',
                           'repeat: true',
52
                           'running: runCount < 2',
53
                           'onTriggered: {',
54
                           'runCount += 1;',
55 56 57 58 59 60 61
                           'var i;',
                           'for (i = 1; i < 2500; ++i) {',
                           'var j = i * i;',
                           'console.log(j);'])
        invokeMenuItem("File", "Save All")
        availableConfigs = iterateBuildConfigs(len(checkedTargets), "Debug")
        if not availableConfigs:
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
            test.fatal("Haven't found a suitable Qt version (need Qt 4.8) - leaving without debugging.")
        else:
            performTest(workingDir, projectName, len(checkedTargets), availableConfigs, False)
            performTest(workingDir, projectName, len(checkedTargets), availableConfigs, True)
    invokeMenuItem("File", "Exit")

def performTest(workingDir, projectName, targetCount, availableConfigs, disableOptimizer):
    for kit, config in availableConfigs:
        qtVersion = selectBuildConfig(targetCount, kit, config)[0]
        test.log("Selected kit using Qt %s" % qtVersion)
        verifyBuildConfig(targetCount, kit, True, enableQmlDebug=True)
        if disableOptimizer:
            batchEditRunEnvironment(targetCount, kit, ["QML_DISABLE_OPTIMIZER=1"])
            switchViewTo(ViewConstants.EDIT)
        # explicitly build before start debugging for adding the executable as allowed program to WinFW
        invokeMenuItem("Build", "Rebuild All")
        waitForSignal("{type='ProjectExplorer::BuildManager' unnamed='1'}",
                      "buildQueueFinished(bool)")
        if not checkCompile():
            test.fatal("Compile had errors... Skipping current build config")
            continue
        allowAppThroughWinFW(workingDir, projectName, False)
        switchViewTo(ViewConstants.ANALYZE)
        selectFromCombo(":Analyzer Toolbar.AnalyzerManagerToolBox_QComboBox", "QML Profiler")
        recordButton = waitForObject("{container=':Qt Creator.Analyzer 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)
        clickButton(waitForObject(":Analyzer Toolbar.Start_QToolButton"))
        stopButton = waitForObject(":Qt Creator.Stop_QToolButton")
        elapsedLabel = waitForObject(":Analyzer Toolbar.Elapsed:_QLabel", 3000)
        waitFor('"Elapsed:    5" in str(elapsedLabel.text)', 20000)
        clickButton(stopButton)
        if safeClickTab("JavaScript"):
            model = findObject(":JavaScript.QmlProfilerEventsTable_QmlProfiler::"
                               "Internal::QV8ProfilerEventsMainView").model()
            test.compare(model.rowCount(), 0)
        if safeClickTab("Events"):
            colPercent, colTotal, colCalls, colMean, colMedian, colLongest, colShortest = range(2, 9)
            model = waitForObject(":Events.QmlProfilerEventsTable_QmlProfiler::"
                                  "Internal::QmlProfilerEventsMainView").model()
            if qtVersion.startswith("5."):
                if disableOptimizer:
                    compareEventsTab(model, "events_qt50_nonOptimized.tsv")
                else:
109
                    compareEventsTab(model, "events_qt50.tsv")
110 111 112 113
                numberOfMsRows = 3
            else:
                if disableOptimizer:
                    compareEventsTab(model, "events_qt48_nonOptimized.tsv")
114
                else:
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
                    compareEventsTab(model, "events_qt48.tsv")
                numberOfMsRows = 2
            test.compare(dumpItems(model, column=colPercent)[0], '100.00 %')
            for i in [colTotal, colMean, colMedian, colLongest, colShortest]:
                for item in dumpItems(model, column=i)[:numberOfMsRows]:
                    test.verify(item.endswith(' ms'), "Verify that '%s' ends with ' ms'" % item)
                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()):
                if str(model.index(row, colCalls).data()) == "1":
                    for col in [colMedian, colLongest, colShortest]:
                        test.compare(model.index(row, colMean).data(), 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(model.index(row, colMedian).data(), model.index(row, colLongest).data(),
                                 "For two calls, median and longest time must be the same.")
        deleteAppFromWinFW(workingDir, projectName, False)
133
        progressBarWait(15000, False)   # wait for "Build" progressbar to disappear
134 135
        clickButton(waitForObject(":Analyzer Toolbar.Clear_QToolButton"))
        test.verify(waitFor("model.rowCount() == 0", 3000), "Analyzer results cleared.")
136

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
def compareEventsTab(model, file):
    significantColumns = [0, 1, 4, 9]

    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)

def containsOnce(tuple, items):
    for item in items:
        if tuple.count(item) != 1:
            return False
    return True

159 160 161 162
def safeClickTab(tab):
    for bar in [":*Qt Creator.JavaScript_QTabBar",
                ":*Qt Creator.Events_QTabBar"]:
        try:
163
            clickOnTab(bar, tab, 1000)
164 165 166 167 168
            return True
        except:
            pass
    test.fail("Tab %s is not being shown." % tab)
    return False
169 170 171 172 173 174

def init():
    removeQmlDebugFolderIfExists()

def cleanup():
    removeQmlDebugFolderIfExists()