summaryrefslogtreecommitdiffstats
path: root/tests/auto/installer
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/installer')
-rw-r--r--tests/auto/installer/appendfileoperation/appendfileoperation.pro10
-rw-r--r--tests/auto/installer/appendfileoperation/data/repository/A/1.0.2-1content.7zbin0 -> 156 bytes
-rw-r--r--tests/auto/installer/appendfileoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 886 bytes
-rw-r--r--tests/auto/installer/appendfileoperation/data/repository/Updates.xml16
-rw-r--r--tests/auto/installer/appendfileoperation/data/xmloperationrepository/A/1.0.0content.7zbin0 -> 133 bytes
-rw-r--r--tests/auto/installer/appendfileoperation/data/xmloperationrepository/Updates.xml20
-rw-r--r--tests/auto/installer/appendfileoperation/settings.qrc9
-rw-r--r--tests/auto/installer/appendfileoperation/tst_appendfileoperation.cpp168
-rw-r--r--tests/auto/installer/archivefactory/archivefactory.pro5
-rw-r--r--tests/auto/installer/archivefactory/tst_archivefactory.cpp144
-rw-r--r--tests/auto/installer/binaryformat/tst_binaryformat.cpp47
-rw-r--r--tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp13
-rw-r--r--tests/auto/installer/clientserver/tst_clientserver.cpp215
-rw-r--r--tests/auto/installer/commandlineinstall/commandlineinstall.pro9
-rw-r--r--tests/auto/installer/commandlineinstall/data/components.xml24
-rw-r--r--tests/auto/installer/commandlineinstall/data/componentsFromInstallPackagesRepository.xml160
-rw-r--r--tests/auto/installer/commandlineinstall/data/config.xml8
-rw-r--r--tests/auto/installer/commandlineinstall/data/filequeryrepository/A/1.0.2-1meta.7zbin0 -> 945 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/filequeryrepository/Updates.xml15
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/Updates.xml72
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentA/2.0.0content.7zbin0 -> 259 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentB/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentC/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentD/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentF/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentH/1.0.0content.7zbin0 -> 209 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml183
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentA/1.0.0content.7zbin0 -> 259 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentB/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentC/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentD/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentE/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentG/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentG/1.0.0meta.7zbin0 -> 970 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentH/1.0.0content.7zbin0 -> 209 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentI/1.0.0content.7zbin0 -> 209 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7zbin0 -> 209 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7zbin0 -> 1010 bytes
-rw-r--r--tests/auto/installer/commandlineinstall/data/repository/Updates.xml69
-rw-r--r--tests/auto/installer/commandlineinstall/data/uninstallableComponentsRepository/Updates.xml50
-rw-r--r--tests/auto/installer/commandlineinstall/settings.qrc37
-rw-r--r--tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp813
-rw-r--r--tests/auto/installer/commandlineupdate/commandlineupdate.pro9
-rw-r--r--tests/auto/installer/commandlineupdate/data/config.xml8
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml179
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentA/1.0.0content.7zbin0 -> 259 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentB/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentC/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentD/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentE/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentG/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentG/1.0.0meta.7zbin0 -> 964 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7zbin0 -> 209 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7zbin0 -> 98 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7zbin0 -> 98 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml163
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentA/1.0.0content.7zbin0 -> 259 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentA/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentB/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentC/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentD/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentE/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent1/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent2/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent1/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent2/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentG/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentG/2.0.0meta.7zbin0 -> 959 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/1.0.0content.7zbin0 -> 209 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7zbin0 -> 225 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/Updates.xml163
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentA/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentB/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentC/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentD/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentE/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent1/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent2/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1/1.0.0content.7zbin0 -> 241 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent1/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent2/1.0.0content.7zbin0 -> 249 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0meta.7zbin0 -> 959 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentH/2.0.0content.7zbin0 -> 225 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/Updates.xml32
-rw-r--r--tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7zbin0 -> 106 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7zbin0 -> 106 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7zbin0 -> 90 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/Updates.xml26
-rw-r--r--tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/componentA/3.0.0content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/componentAutoDependOnA/1.0content.7zbin0 -> 265 bytes
-rw-r--r--tests/auto/installer/commandlineupdate/settings.qrc62
-rw-r--r--tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp418
-rw-r--r--tests/auto/installer/componentalias/componentalias.pro8
-rw-r--r--tests/auto/installer/componentalias/data/aliases-optional.xml44
-rw-r--r--tests/auto/installer/componentalias/data/aliases-priority.xml36
-rw-r--r--tests/auto/installer/componentalias/data/aliases-versions.xml36
-rw-r--r--tests/auto/installer/componentalias/data/aliases.json38
-rw-r--r--tests/auto/installer/componentalias/data/repository/Updates.xml51
-rw-r--r--tests/auto/installer/componentalias/metadata/installer-config/aliases.xml84
-rw-r--r--tests/auto/installer/componentalias/metadata/installer-config/config.xml6
-rw-r--r--tests/auto/installer/componentalias/settings.qrc11
-rw-r--r--tests/auto/installer/componentalias/tst_componentalias.cpp433
-rw-r--r--tests/auto/installer/componentmodel/data/updates.xml12
-rw-r--r--tests/auto/installer/componentmodel/tst_componentmodel.cpp125
-rw-r--r--tests/auto/installer/componentreplace/componentreplace.pro9
-rw-r--r--tests/auto/installer/componentreplace/data/installPackagesRepository/A.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/installPackagesRepository/A/1.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/installPackagesRepository/B.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/installPackagesRepository/B/1.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/installPackagesRepository/C/1.0.0content.7zbin0 -> 152 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/installPackagesRepository/Updates.xml55
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/A.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/A/1.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/B.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/B/1.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/Updates.xml46
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/A.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/A/2.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/B.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/B/2.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7zbin0 -> 152 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/Updates.xml56
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithReplace/A.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithReplace/A/1.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithReplace/B.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithReplace/B/2.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithReplace/Updates.xml46
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/A.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/A/2.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/B.sub1/1.0.0content.7zbin0 -> 207 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/B/2.0.0content.7zbin0 -> 184 bytes
-rw-r--r--tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/Updates.xml46
-rw-r--r--tests/auto/installer/componentreplace/settings.qrc31
-rw-r--r--tests/auto/installer/componentreplace/tst_componentreplace.cpp286
-rw-r--r--tests/auto/installer/consumeoutputoperationtest/consumeoutputoperationtest.pro4
-rw-r--r--tests/auto/installer/consumeoutputoperationtest/data/repository/A/1.0.2-1meta.7zbin0 -> 894 bytes
-rw-r--r--tests/auto/installer/consumeoutputoperationtest/data/repository/Updates.xml15
-rw-r--r--tests/auto/installer/consumeoutputoperationtest/settings.qrc6
-rw-r--r--tests/auto/installer/consumeoutputoperationtest/tst_consumeoutputoperationtest.cpp35
-rw-r--r--tests/auto/installer/contentsha1check/contentsha1check.pro9
-rw-r--r--tests/auto/installer/contentsha1check/data/config.xml8
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7zbin0 -> 175 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha11
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7zbin0 -> 175 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1meta.7zbin0 -> 91 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/Updates.xml27
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7zbin0 -> 148 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha11
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1meta.7zbin0 -> 91 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7zbin0 -> 175 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1meta.7zbin0 -> 91 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/Updates.xml27
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1content.7zbin0 -> 175 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1meta.7zbin0 -> 91 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1content.7zbin0 -> 175 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1meta.7zbin0 -> 91 bytes
-rw-r--r--tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/Updates.xml27
-rw-r--r--tests/auto/installer/contentsha1check/settings.qrc18
-rw-r--r--tests/auto/installer/contentsha1check/tst_contentsha1check.cpp181
-rw-r--r--tests/auto/installer/contentshaupdate/contentshaupdate.pro9
-rw-r--r--tests/auto/installer/contentshaupdate/data/repository/Updates.xml48
-rw-r--r--tests/auto/installer/contentshaupdate/data/repository/componentA/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repository/componentB/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repository/componentC/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repository/componentD/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdate/Updates.xml48
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentA/0.1.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentB/0.1.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentC/2.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentD/2.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml28
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml27
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/contentshaupdate/settings.qrc20
-rw-r--r--tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp124
-rw-r--r--tests/auto/installer/copydirectoryoperation/copydirectoryoperation.pro10
-rw-r--r--tests/auto/installer/copydirectoryoperation/data/repository/A/1.0.2-1content.7zbin0 -> 340 bytes
-rw-r--r--tests/auto/installer/copydirectoryoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 901 bytes
-rw-r--r--tests/auto/installer/copydirectoryoperation/data/repository/Updates.xml16
-rw-r--r--tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/A/1.0.2-1content.7zbin0 -> 340 bytes
-rw-r--r--tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/A/1.0.2-1meta.7zbin0 -> 901 bytes
-rw-r--r--tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/Updates.xml24
-rw-r--r--tests/auto/installer/copydirectoryoperation/settings.qrc9
-rw-r--r--tests/auto/installer/copydirectoryoperation/tst_copydirectoryoperation.cpp217
-rw-r--r--tests/auto/installer/copyoperationtest/copyoperationtest.pro4
-rw-r--r--tests/auto/installer/copyoperationtest/data/repository/A/1.0.2-1content.7zbin0 -> 185 bytes
-rw-r--r--tests/auto/installer/copyoperationtest/data/repository/A/1.0.2-1meta.7zbin0 -> 893 bytes
-rw-r--r--tests/auto/installer/copyoperationtest/data/repository/Updates.xml17
-rw-r--r--tests/auto/installer/copyoperationtest/data/xmloperationrepository/A/1.0.2-1content.7zbin0 -> 185 bytes
-rw-r--r--tests/auto/installer/copyoperationtest/data/xmloperationrepository/Updates.xml25
-rw-r--r--tests/auto/installer/copyoperationtest/settings.qrc9
-rw-r--r--tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp93
-rw-r--r--tests/auto/installer/createdesktopentryoperation/createdesktopentryoperation.pro10
-rw-r--r--tests/auto/installer/createdesktopentryoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 905 bytes
-rw-r--r--tests/auto/installer/createdesktopentryoperation/data/repository/Updates.xml15
-rw-r--r--tests/auto/installer/createdesktopentryoperation/data/xmloperationrepository/Updates.xml18
-rw-r--r--tests/auto/installer/createdesktopentryoperation/settings.qrc7
-rw-r--r--tests/auto/installer/createdesktopentryoperation/tst_createdesktopentryoperation.cpp179
-rw-r--r--tests/auto/installer/createoffline/createoffline.pro9
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-license/2020-12-01-1511_meta.7zbin0 -> 13745 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-license/Updates.xml22
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7zbin0 -> 242 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1meta.7zbin0 -> 13745 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/2020-12-01-1524_meta.7zbin0 -> 1489 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/Updates.xml20
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7zbin0 -> 175 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1meta.7zbin0 -> 1489 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7zbin0 -> 182 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z.sha11
-rw-r--r--tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1meta.7zbin0 -> 106 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/Updates.xml16
-rw-r--r--tests/auto/installer/createoffline/data/repository-componentmeta-script/Updates.xml17
-rw-r--r--tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1meta.7zbin0 -> 1078 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-missingdependency/Updates.xml22
-rw-r--r--tests/auto/installer/createoffline/data/repository-unifiedmeta-script/2020-12-01-1519_meta.7zbin0 -> 1078 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-unifiedmeta-script/Updates.xml18
-rw-r--r--tests/auto/installer/createoffline/data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7zbin0 -> 257 bytes
-rw-r--r--tests/auto/installer/createoffline/data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/createoffline/settings.qrc32
-rw-r--r--tests/auto/installer/createoffline/tst_createoffline.cpp176
-rw-r--r--tests/auto/installer/createshortcutoperation/createshortcutoperation.pro9
-rw-r--r--tests/auto/installer/createshortcutoperation/data/repository/A/1.0.2-1content.7zbin0 -> 185 bytes
-rw-r--r--tests/auto/installer/createshortcutoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 975 bytes
-rw-r--r--tests/auto/installer/createshortcutoperation/data/repository/Updates.xml17
-rw-r--r--tests/auto/installer/createshortcutoperation/data/xmloperationrepository/A/1.0.2-1content.7zbin0 -> 185 bytes
-rw-r--r--tests/auto/installer/createshortcutoperation/data/xmloperationrepository/Updates.xml26
-rw-r--r--tests/auto/installer/createshortcutoperation/installer-config/config.xml6
-rw-r--r--tests/auto/installer/createshortcutoperation/settings.qrc12
-rw-r--r--tests/auto/installer/createshortcutoperation/tst_createshortcutoperation.cpp117
-rw-r--r--tests/auto/installer/deleteoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 871 bytes
-rw-r--r--tests/auto/installer/deleteoperation/data/repository/Updates.xml15
-rw-r--r--tests/auto/installer/deleteoperation/data/xmloperationrepository/Updates.xml17
-rw-r--r--tests/auto/installer/deleteoperation/deleteoperation.pro10
-rw-r--r--tests/auto/installer/deleteoperation/settings.qrc7
-rw-r--r--tests/auto/installer/deleteoperation/tst_deleteoperation.cpp153
-rw-r--r--tests/auto/installer/elevatedexecuteoperation/elevatedexecuteoperation.pro8
-rw-r--r--tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp67
-rw-r--r--tests/auto/installer/environmentvariableoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 882 bytes
-rw-r--r--tests/auto/installer/environmentvariableoperation/data/repository/Updates.xml15
-rw-r--r--tests/auto/installer/environmentvariableoperation/data/xmloperationrepository/Updates.xml25
-rw-r--r--tests/auto/installer/environmentvariableoperation/environmentvariableoperation.pro11
-rw-r--r--tests/auto/installer/environmentvariableoperation/settings.qrc7
-rw-r--r--tests/auto/installer/environmentvariableoperation/tst_environmentvariableoperation.cpp184
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data.qrc12
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0content.7zbin0 -> 98 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0installerbase.7zbin0 -> 114 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/Updates.xml13
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/subdirs.7zbin0 -> 18715 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0anothercontent.7zbin0 -> 114 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content.7zbin0 -> 98 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content1.tar.gzbin0 -> 105 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content2.tar.bz2bin0 -> 125 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content3.tar.xzbin0 -> 152 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content4.zipbin0 -> 202 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0default.7zbin0 -> 98 bytes
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/Updates.xml42
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/extractarchiveoperationtest.pro3
-rw-r--r--tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp135
-rw-r--r--tests/auto/installer/factory/tst_factory.cpp36
-rw-r--r--tests/auto/installer/fileutils/fileutils.pro6
-rw-r--r--tests/auto/installer/fileutils/tst_fileutils.cpp135
-rw-r--r--tests/auto/installer/globalsettingsoperation/globalsettingsoperation.pro10
-rw-r--r--tests/auto/installer/globalsettingsoperation/tst_globalsettingsoperation.cpp95
-rw-r--r--tests/auto/installer/installer.pro46
-rw-r--r--tests/auto/installer/installiconsoperation/data/repository/A/1.0.2-1content.7zbin0 -> 384 bytes
-rw-r--r--tests/auto/installer/installiconsoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 862 bytes
-rw-r--r--tests/auto/installer/installiconsoperation/data/repository/Updates.xml16
-rw-r--r--tests/auto/installer/installiconsoperation/data/xmloperationrepository/A/1.0.2-1content.7zbin0 -> 384 bytes
-rw-r--r--tests/auto/installer/installiconsoperation/data/xmloperationrepository/Updates.xml18
-rw-r--r--tests/auto/installer/installiconsoperation/installiconsoperation.pro10
-rw-r--r--tests/auto/installer/installiconsoperation/settings.qrc9
-rw-r--r--tests/auto/installer/installiconsoperation/tst_installiconsoperation.cpp235
-rw-r--r--tests/auto/installer/lib7zarchive/data.qrc (renamed from tests/auto/installer/lib7zfacade/data.qrc)0
-rw-r--r--tests/auto/installer/lib7zarchive/data/invalid.7z (renamed from tests/auto/installer/lib7zfacade/data/invalid.7z)bin25600 -> 25600 bytes
-rw-r--r--tests/auto/installer/lib7zarchive/data/valid.7z (renamed from tests/auto/installer/lib7zfacade/data/valid.7z)bin950 -> 950 bytes
-rw-r--r--tests/auto/installer/lib7zarchive/lib7zarchive.pro (renamed from tests/auto/installer/lib7zfacade/lib7zfacade.pro)2
-rw-r--r--tests/auto/installer/lib7zarchive/tst_lib7zarchive.cpp149
-rw-r--r--tests/auto/installer/lib7zfacade/tst_lib7zfacade.cpp175
-rw-r--r--tests/auto/installer/libarchivearchive/data.qrc10
-rw-r--r--tests/auto/installer/libarchivearchive/data/valid.7zbin0 -> 950 bytes
-rw-r--r--tests/auto/installer/libarchivearchive/data/valid.qbspbin0 -> 950 bytes
-rw-r--r--tests/auto/installer/libarchivearchive/data/valid.tar.bz2bin0 -> 127 bytes
-rw-r--r--tests/auto/installer/libarchivearchive/data/valid.tar.gzbin0 -> 5194 bytes
-rw-r--r--tests/auto/installer/libarchivearchive/data/valid.tar.xzbin0 -> 964 bytes
-rw-r--r--tests/auto/installer/libarchivearchive/data/valid.zipbin0 -> 5298 bytes
-rw-r--r--tests/auto/installer/libarchivearchive/libarchivearchive.pro7
-rw-r--r--tests/auto/installer/libarchivearchive/tst_libarchivearchive.cpp338
-rw-r--r--tests/auto/installer/licenseagreement/data/repository/A/1.0.2-1meta.7zbin0 -> 11570 bytes
-rw-r--r--tests/auto/installer/licenseagreement/data/repository/Updates.xml17
-rw-r--r--tests/auto/installer/licenseagreement/licenseagreement.pro10
-rw-r--r--tests/auto/installer/licenseagreement/settings.qrc6
-rw-r--r--tests/auto/installer/licenseagreement/tst_licenseagreement.cpp63
-rw-r--r--tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1content.7zbin0 -> 185 bytes
-rw-r--r--tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1content.7z.sha11
-rw-r--r--tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 893 bytes
-rw-r--r--tests/auto/installer/linereplaceoperation/data/repository/Updates.xml17
-rw-r--r--tests/auto/installer/linereplaceoperation/data/xmloperationrepository/A/1.0.2-1content.7zbin0 -> 185 bytes
-rw-r--r--tests/auto/installer/linereplaceoperation/data/xmloperationrepository/A/1.0.2-1content.7z.sha11
-rw-r--r--tests/auto/installer/linereplaceoperation/data/xmloperationrepository/Updates.xml23
-rw-r--r--tests/auto/installer/linereplaceoperation/linereplaceoperation.pro10
-rw-r--r--tests/auto/installer/linereplaceoperation/settings.qrc11
-rw-r--r--tests/auto/installer/linereplaceoperation/tst_linereplaceoperation.cpp153
-rw-r--r--tests/auto/installer/messageboxhandler/data/invalidhash/B/1.0.0-1content.7zbin0 -> 144 bytes
-rw-r--r--tests/auto/installer/messageboxhandler/data/invalidhash/B/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/messageboxhandler/data/invalidhash/Updates.xml15
-rw-r--r--tests/auto/installer/messageboxhandler/data/invalidoperation/A/1.0.2-1meta.7zbin0 -> 875 bytes
-rw-r--r--tests/auto/installer/messageboxhandler/data/invalidoperation/Updates.xml15
-rw-r--r--tests/auto/installer/messageboxhandler/data/messagebox/A/1.0.2-1meta.7zbin0 -> 937 bytes
-rw-r--r--tests/auto/installer/messageboxhandler/data/messagebox/Updates.xml15
-rw-r--r--tests/auto/installer/messageboxhandler/data/missingarchive/C/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/messageboxhandler/data/missingarchive/Updates.xml16
-rw-r--r--tests/auto/installer/messageboxhandler/messageboxhandler.pro6
-rw-r--r--tests/auto/installer/messageboxhandler/settings.qrc13
-rw-r--r--tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp147
-rw-r--r--tests/auto/installer/metadatacache/data/existing-cache/manifest.json7
-rw-r--r--tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/Updates.xml19
-rw-r--r--tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/repository.txt1
-rw-r--r--tests/auto/installer/metadatacache/data/local-temp-repository/A/example-license.txt1
-rw-r--r--tests/auto/installer/metadatacache/data/local-temp-repository/Updates.xml17
-rw-r--r--tests/auto/installer/metadatacache/metadatacache.pro8
-rw-r--r--tests/auto/installer/metadatacache/settings.qrc9
-rw-r--r--tests/auto/installer/metadatacache/tst_metadatacache.cpp381
-rw-r--r--tests/auto/installer/metadatajob/data/repository/C/1.0.0-1content.7zbin0 -> 182 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repository/C/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/metadatajob/data/repository/C/1.0.0-1meta.7zbin0 -> 106 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repository/Updates.xml16
-rw-r--r--tests/auto/installer/metadatajob/data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7zbin0 -> 1057 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1content.7zbin0 -> 182 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1content.7z.sha11
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1meta.7zbin0 -> 106 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1content.7zbin0 -> 182 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1meta.7zbin0 -> 106 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionAdd/Updates.xml30
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1content.7zbin0 -> 182 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1content.7z.sha11
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1meta.7zbin0 -> 106 bytes
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryActionRemove/Updates.xml19
-rw-r--r--tests/auto/installer/metadatajob/data/repositoryZipped/repositoryZipped.7zbin0 -> 931 bytes
-rw-r--r--tests/auto/installer/metadatajob/metadatajob.pro8
-rw-r--r--tests/auto/installer/metadatajob/settings.qrc9
-rw-r--r--tests/auto/installer/metadatajob/tst_metadatajob.cpp148
-rw-r--r--tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp28
-rw-r--r--tests/auto/installer/moveoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 909 bytes
-rw-r--r--tests/auto/installer/moveoperation/data/repository/Updates.xml15
-rw-r--r--tests/auto/installer/moveoperation/data/xmloperationrepository/Updates.xml22
-rw-r--r--tests/auto/installer/moveoperation/moveoperation.pro10
-rw-r--r--tests/auto/installer/moveoperation/settings.qrc7
-rw-r--r--tests/auto/installer/moveoperation/tst_moveoperation.cpp151
-rw-r--r--tests/auto/installer/packagemanagercore/installer-config/config.xml5
-rw-r--r--tests/auto/installer/packagemanagercore/settings.qrc1
-rw-r--r--tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp80
-rw-r--r--tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1content.7zbin0 -> 129 bytes
-rw-r--r--tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1meta.7zbin0 -> 910 bytes
-rw-r--r--tests/auto/installer/prependfileoperation/data/repository/Updates.xml16
-rw-r--r--tests/auto/installer/prependfileoperation/data/xmloperationrepository/C/1.0.0content.7zbin0 -> 129 bytes
-rw-r--r--tests/auto/installer/prependfileoperation/data/xmloperationrepository/Updates.xml20
-rw-r--r--tests/auto/installer/prependfileoperation/prependfileoperation.pro10
-rw-r--r--tests/auto/installer/prependfileoperation/settings.qrc9
-rw-r--r--tests/auto/installer/prependfileoperation/tst_prependfileoperation.cpp180
-rw-r--r--tests/auto/installer/registerfiletypeoperation/data/repository/A/1.0.2-1content.7zbin0 -> 185 bytes
-rw-r--r--tests/auto/installer/registerfiletypeoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 975 bytes
-rw-r--r--tests/auto/installer/registerfiletypeoperation/data/repository/Updates.xml17
-rw-r--r--tests/auto/installer/registerfiletypeoperation/registerfiletypeoperation.pro4
-rw-r--r--tests/auto/installer/registerfiletypeoperation/settings.qrc7
-rw-r--r--tests/auto/installer/registerfiletypeoperation/tst_registerfiletypeoperation.cpp140
-rw-r--r--tests/auto/installer/replaceoperation/data/repository/A/1.0.2-1content.7zbin0 -> 185 bytes
-rw-r--r--tests/auto/installer/replaceoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 912 bytes
-rw-r--r--tests/auto/installer/replaceoperation/data/repository/Updates.xml17
-rw-r--r--tests/auto/installer/replaceoperation/replaceoperation.pro4
-rw-r--r--tests/auto/installer/replaceoperation/settings.qrc7
-rw-r--r--tests/auto/installer/replaceoperation/tst_replaceoperation.cpp32
-rw-r--r--tests/auto/installer/repository/data/compressedRepository/compressedRepository.7zbin0 -> 590 bytes
-rw-r--r--tests/auto/installer/repository/data/repository/A/1.0.2content.7zbin0 -> 165 bytes
-rw-r--r--tests/auto/installer/repository/data/repository/A/1.0.2meta.7zbin0 -> 979 bytes
-rw-r--r--tests/auto/installer/repository/data/repository/B/1.0.0meta.7zbin0 -> 998 bytes
-rw-r--r--tests/auto/installer/repository/data/repository/C/1.0.0meta.7zbin0 -> 994 bytes
-rw-r--r--tests/auto/installer/repository/data/repository/Updates.xml33
-rw-r--r--tests/auto/installer/repository/repository.pro4
-rw-r--r--tests/auto/installer/repository/settings.qrc10
-rw-r--r--tests/auto/installer/repository/tst_repository.cpp149
-rw-r--r--tests/auto/installer/rmdiroperationtest/rmdiroperationtest.pro6
-rw-r--r--tests/auto/installer/rmdiroperationtest/tst_rmdiroperationtest.cpp111
-rw-r--r--tests/auto/installer/scriptengine/data/addOperation.qs29
-rw-r--r--tests/auto/installer/scriptengine/data/auto-install.qs2
-rw-r--r--tests/auto/installer/scriptengine/tst_scriptengine.cpp77
-rw-r--r--tests/auto/installer/settings/data/full_config.xml2
-rw-r--r--tests/auto/installer/settings/data/length_units_invalid.xml2
-rw-r--r--tests/auto/installer/settings/data/length_units_valid_em.xml2
-rw-r--r--tests/auto/installer/settings/data/length_units_valid_ex.xml2
-rw-r--r--tests/auto/installer/settings/data/length_units_valid_px.xml2
-rw-r--r--tests/auto/installer/settings/tst_settings.cpp43
-rw-r--r--tests/auto/installer/settingsoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 927 bytes
-rw-r--r--tests/auto/installer/settingsoperation/data/repository/B/1.0.0meta.7zbin0 -> 967 bytes
-rw-r--r--tests/auto/installer/settingsoperation/data/repository/C/1.0.0meta.7zbin0 -> 958 bytes
-rw-r--r--tests/auto/installer/settingsoperation/data/repository/Updates.xml33
-rw-r--r--tests/auto/installer/settingsoperation/settings.qrc8
-rw-r--r--tests/auto/installer/settingsoperation/settingsoperation.pro3
-rw-r--r--tests/auto/installer/settingsoperation/tst_settingsoperation.cpp103
-rw-r--r--tests/auto/installer/shared/config.qrc5
-rw-r--r--tests/auto/installer/shared/installer-config/config.xml5
-rw-r--r--tests/auto/installer/shared/packagemanager.h82
-rw-r--r--tests/auto/installer/shared/verifyinstaller.h139
-rw-r--r--tests/auto/installer/simplemovefileoperation/data/repository/A/1.0.2-1meta.7zbin0 -> 892 bytes
-rw-r--r--tests/auto/installer/simplemovefileoperation/data/repository/Updates.xml15
-rw-r--r--tests/auto/installer/simplemovefileoperation/settings.qrc6
-rw-r--r--tests/auto/installer/simplemovefileoperation/simplemovefileoperation.pro10
-rw-r--r--tests/auto/installer/simplemovefileoperation/tst_simplemovefileoperation.cpp178
-rw-r--r--tests/auto/installer/solver/tst_solver.cpp91
-rw-r--r--tests/auto/installer/treename/data/components.xml59
-rw-r--r--tests/auto/installer/treename/data/invalid_repository/Updates.xml55
-rw-r--r--tests/auto/installer/treename/data/repository/Updates.xml135
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0meta.7zbin0 -> 138 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0meta.7zbin0 -> 138 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA/1.0.0content.7zbin0 -> 235 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentA/1.0.0meta.7zbin0 -> 130 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7zbin0 -> 251 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0meta.7zbin0 -> 146 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7zbin0 -> 251 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0meta.7zbin0 -> 146 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0meta.7zbin0 -> 138 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7zbin0 -> 243 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0meta.7zbin0 -> 138 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB/1.0.0content.7zbin0 -> 235 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentB/1.0.0meta.7zbin0 -> 130 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentC/1.0.0content.7zbin0 -> 235 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentC/1.0.0meta.7zbin0 -> 130 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentD/1.0.0content.7zbin0 -> 235 bytes
-rw-r--r--tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z.sha11
-rw-r--r--tests/auto/installer/treename/data/repository/componentD/1.0.0meta.7zbin0 -> 130 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/Updates.xml229
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentA.subcomponent1/1.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentA.subcomponent1/1.0.0meta.7zbin0 -> 137 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentA/1.0.0content.7zbin0 -> 223 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentA/1.0.0meta.7zbin0 -> 109 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentB/1.0.0content.7zbin0 -> 223 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentB/1.0.0meta.7zbin0 -> 109 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentE/1.0.0content.7zbin0 -> 223 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentE/1.0.0meta.7zbin0 -> 109 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0content.7zbin0 -> 231 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0meta.7zbin0 -> 171 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0content.7zbin0 -> 231 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0meta.7zbin0 -> 171 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent1/1.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent1/1.0.0meta.7zbin0 -> 137 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0content.7zbin0 -> 231 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0meta.7zbin0 -> 171 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0content.7zbin0 -> 231 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0meta.7zbin0 -> 171 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent2/1.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF.subcomponent2/1.0.0meta.7zbin0 -> 137 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF/1.0.0content.7zbin0 -> 223 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentF/1.0.0meta.7zbin0 -> 109 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentH.subcomponent1/1.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentH.subcomponent1/1.0.0meta.7zbin0 -> 137 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentH/1.0.0content.7zbin0 -> 223 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentH/1.0.0meta.7zbin0 -> 109 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentI.subcomponent1/1.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentI.subcomponent1/1.0.0meta.7zbin0 -> 137 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentI.subcomponent2/1.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentI.subcomponent2/1.0.0meta.7zbin0 -> 137 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentJ.subcomponent1/1.0.0content.7zbin0 -> 227 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentJ.subcomponent1/1.0.0meta.7zbin0 -> 137 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentJ/1.0.0content.7zbin0 -> 223 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentJ/1.0.0meta.7zbin0 -> 109 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentK/1.0.0content.7zbin0 -> 223 bytes
-rw-r--r--tests/auto/installer/treename/data/repository_children/componentK/1.0.0meta.7zbin0 -> 109 bytes
-rw-r--r--tests/auto/installer/treename/settings.qrc65
-rw-r--r--tests/auto/installer/treename/treename.pro10
-rw-r--r--tests/auto/installer/treename/tst_treename.cpp457
-rw-r--r--tests/auto/installer/unicodeexecutable/main.c32
-rw-r--r--tests/auto/installer/unicodeexecutable/stringdata.h32
513 files changed, 12191 insertions, 514 deletions
diff --git a/tests/auto/installer/appendfileoperation/appendfileoperation.pro b/tests/auto/installer/appendfileoperation/appendfileoperation.pro
new file mode 100644
index 000000000..aca9ffd36
--- /dev/null
+++ b/tests/auto/installer/appendfileoperation/appendfileoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_appendfileoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/appendfileoperation/data/repository/A/1.0.2-1content.7z b/tests/auto/installer/appendfileoperation/data/repository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..787e0db25
--- /dev/null
+++ b/tests/auto/installer/appendfileoperation/data/repository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/appendfileoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/appendfileoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..946290ce4
--- /dev/null
+++ b/tests/auto/installer/appendfileoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/appendfileoperation/data/repository/Updates.xml b/tests/auto/installer/appendfileoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..f12d387a1
--- /dev/null
+++ b/tests/auto/installer/appendfileoperation/data/repository/Updates.xml
@@ -0,0 +1,16 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>750eda14d867849aeb2f47d620f6e5f32134f375</SHA1>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/appendfileoperation/data/xmloperationrepository/A/1.0.0content.7z b/tests/auto/installer/appendfileoperation/data/xmloperationrepository/A/1.0.0content.7z
new file mode 100644
index 000000000..90b958cdb
--- /dev/null
+++ b/tests/auto/installer/appendfileoperation/data/xmloperationrepository/A/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/appendfileoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/appendfileoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..708ba6539
--- /dev/null
+++ b/tests/auto/installer/appendfileoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,20 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2020-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Operations>
+ <Operation name="AppendFile">
+ <Argument>@TargetDir@/A.txt</Argument>
+ <Argument>lorem ipsum</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/appendfileoperation/settings.qrc b/tests/auto/installer/appendfileoperation/settings.qrc
new file mode 100644
index 000000000..66d0c8da1
--- /dev/null
+++ b/tests/auto/installer/appendfileoperation/settings.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1content.7z</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ <file>data/xmloperationrepository/A/1.0.0content.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/appendfileoperation/tst_appendfileoperation.cpp b/tests/auto/installer/appendfileoperation/tst_appendfileoperation.cpp
new file mode 100644
index 000000000..743e4c625
--- /dev/null
+++ b/tests/auto/installer/appendfileoperation/tst_appendfileoperation.cpp
@@ -0,0 +1,168 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+
+#include <updateoperations.h>
+#include <packagemanagercore.h>
+
+#include <QFile>
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_appendfileoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, repository);
+ core->installDefaultComponentsSilently();
+
+ QFile file(installDir + QDir::separator() + "A.txt");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ QTextStream stream(&file);
+ QCOMPARE(stream.readAll(), QLatin1String("Appended text: lorem ipsum"));
+ file.close();
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+ // We cannot check the file contents here as it will be deleted on
+ // undo Extract, but at least check that the uninstallation succeeds.
+ QCOMPARE(PackageManagerCore::Success, core->uninstallComponentsSilently
+ (QStringList()<< "A"));
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_testFilePath = qApp->applicationDirPath() + QDir::toNativeSeparators("/test");
+ }
+
+ void testMissingArguments()
+ {
+ AppendFileOperation op;
+
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in AppendFile: 0 arguments given, 2 to 4 arguments expected in the form: <filename> <text to apply> [UNDOOPERATION, \"\"]."));
+
+ op.setArguments(QStringList() << "" << "");
+ QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified");
+ QTest::ignoreMessage(QtWarningMsg, "QFile::rename: Empty or null file name");
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError);
+ QCOMPARE(op.errorString(), QString("Cannot open file \"\" for writing: No file name specified"));
+ }
+
+ void testAppendText_data()
+ {
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QString>("append");
+ QTest::addColumn<QString>("expected");
+ QTest::addColumn<bool>("overrideUndo");
+ QTest::newRow("newline") << "Line1\nLine2\nLine3\n" << "AppendedText"
+ << "Line1\nLine2\nLine3\nAppendedText" << false;
+ QTest::newRow("no newline") << "Lorem ipsum " << "dolore sit amet"
+ << "Lorem ipsum dolore sit amet" << false;
+
+ QTest::newRow("no undo") << "Lorem ipsum " << "dolore sit amet"
+ << "Lorem ipsum dolore sit amet" << true;
+ }
+
+ void testAppendText()
+ {
+ QFETCH(QString, source);
+ QFETCH(QString, append);
+ QFETCH(QString, expected);
+ QFETCH(bool, overrideUndo);
+
+ QFile file(m_testFilePath);
+ QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
+
+ QTextStream stream(&file);
+ stream << source << Qt::flush;
+ file.close();
+
+ AppendFileOperation *op = new AppendFileOperation();
+ op->setArguments(QStringList() << m_testFilePath << append);
+ if (overrideUndo)
+ op->setArguments(op->arguments() << QLatin1String("UNDOOPERATION"));
+
+ op->backup();
+ QVERIFY(QFileInfo(op->value("backupOfFile").toString()).exists());
+
+ QVERIFY2(op->performOperation(), op->errorString().toLatin1());
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ QCOMPARE(stream.readAll(), expected);
+ file.close();
+
+ QVERIFY2(op->undoOperation(), op->errorString().toLatin1());
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ if (overrideUndo)
+ QCOMPARE(stream.readAll(), expected);
+ else
+ QCOMPARE(stream.readAll(), source);
+ QString backupFileName = op->value("backupOfFile").toString();
+ delete op;
+ QVERIFY(!QFileInfo::exists(backupFileName));
+
+ file.close();
+
+ QVERIFY(file.remove());
+ }
+
+ void testApppendFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testAppendFromComponentXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+
+private:
+ QString m_testFilePath;
+};
+
+QTEST_MAIN(tst_appendfileoperation)
+
+#include "tst_appendfileoperation.moc"
diff --git a/tests/auto/installer/archivefactory/archivefactory.pro b/tests/auto/installer/archivefactory/archivefactory.pro
new file mode 100644
index 000000000..3d8ee90ab
--- /dev/null
+++ b/tests/auto/installer/archivefactory/archivefactory.pro
@@ -0,0 +1,5 @@
+include(../../qttest.pri)
+
+QT -= gui
+
+SOURCES += tst_archivefactory.cpp
diff --git a/tests/auto/installer/archivefactory/tst_archivefactory.cpp b/tests/auto/installer/archivefactory/tst_archivefactory.cpp
new file mode 100644
index 000000000..0c1a7b6f6
--- /dev/null
+++ b/tests/auto/installer/archivefactory/tst_archivefactory.cpp
@@ -0,0 +1,144 @@
+/**************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include <archivefactory.h>
+
+#include <QObject>
+#include <QTest>
+
+using namespace QInstaller;
+
+class MyRarArchive : public AbstractArchive
+{
+ Q_OBJECT
+
+public:
+ MyRarArchive(QObject *parent = nullptr)
+ : AbstractArchive(parent)
+ {}
+ MyRarArchive(const QString &filename, QObject *parent = nullptr)
+ : AbstractArchive(parent)
+ {
+ Q_UNUSED(filename)
+ }
+
+ bool open(QIODevice::OpenMode mode)
+ {
+ Q_UNUSED(mode)
+ return true;
+ };
+ void close() {};
+ void setFilename(const QString &filename) { Q_UNUSED(filename) };
+ bool extract(const QString &dirPath)
+ {
+ Q_UNUSED(dirPath)
+ return true;
+ };
+ bool extract(const QString &dirPath, const quint64 totalFiles)
+ {
+ Q_UNUSED(dirPath)
+ Q_UNUSED(totalFiles)
+ return true;
+ };
+ bool create(const QStringList &data)
+ {
+ Q_UNUSED(data)
+ return true;
+ };
+ QVector<ArchiveEntry> list() { return QVector<ArchiveEntry>(); };
+ bool isSupported() { return true; };
+
+public slots:
+ void cancel() {};
+};
+
+class tst_archivefactory : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testCreateDefaultArchiveHandler_data()
+ {
+ QTest::addColumn<QString>("handler");
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<QStringList>("types");
+#ifdef IFW_LIBARCHIVE
+ QTest::newRow("LibArchive")
+ << "LibArchive" << "myfile.zip"
+ << (QStringList() << "tar" << "tar.gz" << "tar.bz2" << "tar.xz" << "zip" << "7z" << "qbsp");
+#elif defined(IFW_LIB7Z)
+ QTest::newRow("Lib7z")
+ << "Lib7z" << "myfile.7z" << (QStringList() << "7z" << "qbsp");
+#endif
+ }
+
+ void testCreateDefaultArchiveHandler()
+ {
+ QFETCH(QString, handler);
+ QFETCH(QString, filename);
+ QFETCH(QStringList, types);
+
+ QVERIFY(ArchiveFactory::instance().containsProduct(handler));
+ for (auto &type : types)
+ QVERIFY(ArchiveFactory::isSupportedType("file." + type));
+
+ QScopedPointer<AbstractArchive> archive(ArchiveFactory::instance().create(filename));
+ QVERIFY(archive);
+ }
+
+ void testCreateUnknownArchive_data()
+ {
+ QTest::addColumn<QString>("filename");
+ QTest::newRow("Unknown suffix") << "invalid.file";
+ QTest::newRow("Suffix with known part 1") << "myfile.7z.sha1";
+ QTest::newRow("Suffix with known part 2") << "myfile.tar.gz.sha1";
+ }
+
+ void testCreateUnknownArchive()
+ {
+ QFETCH(QString, filename);
+
+ QVERIFY(!ArchiveFactory::isSupportedType(filename));
+ QScopedPointer<AbstractArchive> archive(ArchiveFactory::instance().create(filename));
+ QVERIFY(!archive);
+ }
+
+ void testRegisterNewHandler()
+ {
+ ArchiveFactory::instance().registerArchive<MyRarArchive>("MyRarHandler", QStringList() << "rar");
+ QVERIFY(ArchiveFactory::instance().containsProduct("MyRarHandler"));
+ QVERIFY(ArchiveFactory::isSupportedType("file.rar"));
+
+ QScopedPointer<AbstractArchive> archive(ArchiveFactory::instance().create("myfile.rar"));
+ QVERIFY(archive);
+ }
+};
+
+QTEST_MAIN(tst_archivefactory)
+
+#include "tst_archivefactory.moc"
diff --git a/tests/auto/installer/binaryformat/tst_binaryformat.cpp b/tests/auto/installer/binaryformat/tst_binaryformat.cpp
index c9cd2b00f..2fcad0b38 100644
--- a/tests/auto/installer/binaryformat/tst_binaryformat.cpp
+++ b/tests/auto/installer/binaryformat/tst_binaryformat.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -26,6 +26,8 @@
**
**************************************************************************/
+#include "../shared/packagemanager.h"
+
#include <binarycontent.h>
#include <binaryformat.h>
#include <errors.h>
@@ -51,8 +53,8 @@ struct Layout : public QInstaller::BinaryLayout
class TestOperation : public KDUpdater::UpdateOperation
{
public:
- TestOperation(const QString &name)
- : KDUpdater::UpdateOperation(nullptr)
+ explicit TestOperation(const QString &name, PackageManagerCore *core = nullptr)
+ : KDUpdater::UpdateOperation(core)
{ setName(name); }
virtual void backup() {}
@@ -392,6 +394,45 @@ private slots:
resource->close();
}
+ void testXmlDocumentParsing()
+ {
+ PackageManagerCore core;
+ core.setValue(scTargetDir, QLatin1String("relocatable_targetdir"));
+
+ TestOperation op(QLatin1String("Operation 3"), &core);
+ QStringList stringListValue = (QStringList() << QLatin1String("list_value1") << QLatin1String("list_value2"));
+ op.setValue(QLatin1String("string_list"), stringListValue);
+
+ const QString stringValue = core.value(scTargetDir) + QLatin1String(", string_value1");
+ op.setValue(QLatin1String("string"), stringValue);
+
+ QVariantMap map;
+ map.insert(QLatin1String("key1"), 1);
+ map.insert(QLatin1String("key2"), QLatin1String("map_value2"));
+ op.setValue(QLatin1String("variant_map"), map);
+
+ QDomDocument document = op.toXml();
+ QVERIFY2(document.toString().contains(QLatin1String("@RELOCATABLE_PATH@")),
+ "TargetDir not replaced with @RELOCATABLE_PATH@");
+
+ op.fromXml(document); // Resets the operation values from written QDomDocuments
+
+ QCOMPARE(op.value(QLatin1String("string_list")), stringListValue);
+ QVERIFY2(!op.value(QLatin1String("string")).toString().contains(QLatin1String("@RELOCATABLE_PATH@")),
+ "@RELOCATABLE@ not replaced with TargetDir");
+ QCOMPARE(op.value(QLatin1String("variant_map")), map);
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ QCOMPARE(op.value(QLatin1String("string_list")).metaType().id(), QMetaType::QStringList);
+ QCOMPARE(op.value(QLatin1String("string")).metaType().id(), QMetaType::QString);
+ QCOMPARE(op.value(QLatin1String("variant_map")).metaType().id(), QMetaType::QVariantMap);
+#else
+ QCOMPARE(op.value(QLatin1String("string_list")).type(), QMetaType::QStringList);
+ QCOMPARE(op.value(QLatin1String("string")).type(), QMetaType::QString);
+ QCOMPARE(op.value(QLatin1String("variant_map")).type(), QMetaType::QVariantMap);
+#endif
+ }
+
void cleanupTestCase()
{
m_manager.clear();
diff --git a/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp b/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp
index 95f4ac77d..5978b3bb2 100644
--- a/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp
+++ b/tests/auto/installer/brokeninstaller/tst_brokeninstaller.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -100,7 +100,7 @@ private slots:
QList<Component*> rootComponents = loadComponents(core);
ComponentModel *model = new ComponentModel(1, &core);
- model->setRootComponents(rootComponents);
+ model->reset(rootComponents);
// all names should be resolvable
QStringList all;
all << m_checkedComponentsWithBrokenScript << m_uncheckedComponentsWithBrokenScript << m_partiallyCheckedComponentsWithBrokenScript;
@@ -125,9 +125,9 @@ private slots:
const QString debugMessage = QString("Exception while loading the component script");
const QRegularExpression re(debugMessage);
QTest::ignoreMessage(QtWarningMsg, re);
- invalidScriptComponent->loadComponentScript(":///data/broken_script.qs");
+ invalidScriptComponent->evaluateComponentScript(":///data/broken_script.qs");
- model->setRootComponents(components);
+ model->reset(components);
testModelState(model, m_checkedComponentsWithBrokenScript, m_partiallyCheckedComponentsWithBrokenScript, m_uncheckedComponentsWithBrokenScript);
}
@@ -145,8 +145,8 @@ private slots:
Component *componentDependingOnMissingDependency = core.componentByName("componentd");
componentDependingOnMissingDependency->addDependency("componentmissingdependency");
- core.componentsToInstallNeedsRecalculation();
- model->setRootComponents(components);
+ core.recalculateAllComponents();
+ model->reset(components);
testModelState(model, m_checkedComponentsWithMissingDependency, m_partiallyCheckedComponentsWithBrokenScript, m_uncheckedComponentsWithMissingDependency);
}
@@ -157,6 +157,7 @@ private:
{
UpdatesInfo updatesInfo;
updatesInfo.setFileName(":///data/updates.xml");
+ updatesInfo.parseFile();
const QList<UpdateInfo> updateInfos = updatesInfo.updatesInfo();
QList <Component*> components;
diff --git a/tests/auto/installer/clientserver/tst_clientserver.cpp b/tests/auto/installer/clientserver/tst_clientserver.cpp
index b3e220c9f..7b3e65c4a 100644
--- a/tests/auto/installer/clientserver/tst_clientserver.cpp
+++ b/tests/auto/installer/clientserver/tst_clientserver.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -26,12 +26,20 @@
**
**************************************************************************/
+#include "../shared/verifyinstaller.h"
+#include "../shared/packagemanager.h"
+
#include <protocol.h>
#include <qprocesswrapper.h>
#include <qsettingswrapper.h>
#include <remoteclient.h>
#include <remotefileengine.h>
#include <remoteserver.h>
+#include <fileutils.h>
+
+#ifdef IFW_LIBARCHIVE
+#include <libarchivewrapper_p.h>
+#endif
#include <QBuffer>
#include <QSettings>
@@ -44,6 +52,17 @@
using namespace QInstaller;
+class MyRemoteObject : public RemoteObject
+{
+public:
+ MyRemoteObject()
+ : RemoteObject(QLatin1String("MyRemoteObject")) {};
+
+ ~MyRemoteObject() = default;
+
+ bool connectToServer() { return RemoteObject::connectToServer(); }
+};
+
class tst_ClientServer : public QObject
{
Q_OBJECT
@@ -71,7 +90,7 @@ private:
}
private slots:
- void initTestCase()
+ void init()
{
RemoteClient::instance().setActive(true);
}
@@ -153,44 +172,42 @@ private slots:
const QByteArray message(10905, '0');
QLocalServer server;
- { // server
- QLocalSocket *rcv = 0;
- auto srvDataArrived = [&]() {
- QByteArray command, message;
- if (!receivePacket(rcv, &command, &message))
- return;
- sendPacket(rcv, command, message);
- };
-
- connect(&server, &QLocalServer::newConnection, [&,srvDataArrived]() {
- rcv = server.nextPendingConnection();
- connect(rcv, &QLocalSocket::readyRead, srvDataArrived);
- });
+ // server
+ QLocalSocket *rcv = 0;
+ auto srvDataArrived = [&]() {
+ QByteArray command, message;
+ if (!receivePacket(rcv, &command, &message))
+ return;
+ sendPacket(rcv, command, message);
+ };
- server.listen(socketName);
- }
+ connect(&server, &QLocalServer::newConnection, [&,srvDataArrived]() {
+ rcv = server.nextPendingConnection();
+ connect(rcv, &QLocalSocket::readyRead, srvDataArrived);
+ });
+
+ server.listen(socketName);
QLocalSocket snd;
- { // client
- auto clientDataArrived = [&]() {
- QByteArray cmd, msg;
- if (!receivePacket(&snd, &cmd, &msg))
- return;
- QCOMPARE(cmd, command);
- QCOMPARE(msg, message);
- loop.exit();
- };
-
- connect(&snd, &QLocalSocket::readyRead, clientDataArrived);
-
- QTimer::singleShot(0, [&]() {
- snd.connect(&snd, &QLocalSocket::connected, [&](){
- sendPacket(&snd, command, message);
- });
- snd.connectToServer(socketName);
+ // client
+ auto clientDataArrived = [&]() {
+ QByteArray cmd, msg;
+ if (!receivePacket(&snd, &cmd, &msg))
+ return;
+ QCOMPARE(cmd, command);
+ QCOMPARE(msg, message);
+ loop.exit();
+ };
+
+ connect(&snd, &QLocalSocket::readyRead, clientDataArrived);
+
+ QTimer::singleShot(0, [&]() {
+ snd.connect(&snd, &QLocalSocket::connected, [&](){
+ sendPacket(&snd, command, message);
});
- }
+ snd.connectToServer(socketName);
+ });
loop.exec();
}
@@ -264,8 +281,48 @@ private slots:
}
}
+ void testCreateDestroyRemoteObject()
+ {
+ RemoteServer server;
+ QString socketName = QUuid::createUuid().toString();
+ server.init(socketName, QLatin1String("SomeKey"), Protocol::Mode::Production);
+ server.start();
+
+ RemoteClient::instance().init(socketName, QLatin1String("SomeKey"), Protocol::Mode::Debug,
+ Protocol::StartAs::User);
+
+ // Look for warnings on connection and disconnection..
+ qInstallMessageHandler(exitOnWarningMessageHandler);
+
+ MyRemoteObject *object = new MyRemoteObject;
+ QVERIFY(!object->isConnectedToServer());
+ delete object;
+
+ object = new MyRemoteObject;
+ QVERIFY(object->connectToServer());
+ QVERIFY(object->isConnectedToServer());
+ delete object;
+
+ object = new MyRemoteObject;
+ QVERIFY(object->connectToServer());
+ QVERIFY(object->isConnectedToServer());
+
+ RemoteClient::instance().setActive(false);
+ QVERIFY(!object->isConnectedToServer());
+ delete object;
+ }
+
+ void testQSettingsWrapper_data()
+ {
+ QTest::addColumn<QSettings::Format>("format");
+ QTest::newRow("Native format") << QSettings::NativeFormat;
+ QTest::newRow("INI format") << QSettings::IniFormat;
+ }
+
void testQSettingsWrapper()
{
+ QFETCH(QSettings::Format, format);
+
RemoteServer server;
QString socketName = QUuid::createUuid().toString();
server.init(socketName, QLatin1String("SomeKey"), Protocol::Mode::Production);
@@ -274,14 +331,15 @@ private slots:
RemoteClient::instance().init(socketName, QLatin1String("SomeKey"), Protocol::Mode::Debug,
Protocol::StartAs::User);
- QSettingsWrapper wrapper("digia", "clientserver");
+ QSettingsWrapper wrapper(format, QSettingsWrapper::UserScope, "digia", "clientserver");
+
QCOMPARE(wrapper.isConnectedToServer(), false);
wrapper.clear();
QCOMPARE(wrapper.isConnectedToServer(), true);
wrapper.sync();
wrapper.setFallbacksEnabled(false);
- QSettings settings("digia", "clientserver");
+ QSettings settings(format, QSettings::UserScope, "digia", "clientserver");
settings.setFallbacksEnabled(false);
QCOMPARE(settings.fileName(), wrapper.fileName());
@@ -310,6 +368,29 @@ private slots:
QCOMPARE(wrapper.contains("key"), false);
QCOMPARE(settings.contains("key"), false);
+ const QDateTime dateTime = QDateTime::currentDateTimeUtc();
+ // The wrapper does not support this method, but assume:
+ // QCOMPARE(wrapper.iniCodec(), QTextCodec::codecForName("UTF-8"));
+ wrapper.setValue("dateTime", dateTime);
+ wrapper.sync();
+ QCOMPARE(wrapper.value("dateTime").toDateTime(), dateTime);
+ QCOMPARE(settings.value("dateTime").toDateTime(), dateTime);
+
+ wrapper.remove("dateTime");
+ wrapper.sync();
+ QCOMPARE(wrapper.contains("dateTime"), false);
+ QCOMPARE(settings.contains("dateTime"), false);
+
+ settings.setValue("dateTime", dateTime);
+ settings.sync();
+ QCOMPARE(wrapper.value("dateTime").toDateTime(), dateTime);
+ QCOMPARE(settings.value("dateTime").toDateTime(), dateTime);
+
+ settings.remove("dateTime");
+ settings.sync();
+ QCOMPARE(wrapper.contains("dateTime"), false);
+ QCOMPARE(settings.contains("dateTime"), false);
+
wrapper.beginGroup("group");
wrapper.setValue("key", "value");
wrapper.endGroup();
@@ -386,6 +467,9 @@ private slots:
void testQProcessWrapper()
{
+ #ifdef Q_OS_LINUX
+ QSKIP("This test failes in CI redhat");
+ #endif
RemoteServer server;
QString socketName = QUuid::createUuid().toString();
server.init(socketName, QLatin1String("SomeKey"), Protocol::Mode::Production);
@@ -503,7 +587,7 @@ private slots:
QFile file;
file.setFileName(filename);
file.open(QIODevice::ReadWrite);
- const QByteArray ba = file.readLine();
+ file.readLine();
file.seek(0);
QCOMPARE(file.atEnd(), false);
@@ -515,6 +599,61 @@ private slots:
QCOMPARE(file.atEnd(), true);
}
+ void testArchiveWrapper_data()
+ {
+ QTest::addColumn<QString>("suffix");
+ QTest::newRow("ZIP archive") << ".zip";
+ QTest::newRow("uncompressed tar archive") << ".tar";
+ QTest::newRow("gzip compressed tar archive") << ".tar.gz";
+ QTest::newRow("bzip2 compressed tar archive") << ".tar.bz2";
+ QTest::newRow("xz compressed tar archive") << ".tar.xz";
+ QTest::newRow("7zip archive") << ".7z";
+ }
+
+ void testArchiveWrapper()
+ {
+#ifndef IFW_LIBARCHIVE
+ QSKIP("Installer Framework built without libarchive support");
+#else
+ QFETCH(QString, suffix);
+
+ const QString archiveName = generateTemporaryFileName() + suffix;
+ const QString targetName = QDir::tempPath() + "/tst_archivewrapper/";
+
+ QTemporaryFile source;
+ source.open();
+ source.write("Source File");
+ source.setAutoRemove(false);
+
+ RemoteServer server;
+ QString socketName = QUuid::createUuid().toString();
+ server.init(socketName, QLatin1String("SomeKey"), Protocol::Mode::Production);
+ server.start();
+
+ RemoteClient::instance().init(socketName, QLatin1String("SomeKey"), Protocol::Mode::Debug,
+ Protocol::StartAs::User);
+
+ LibArchiveWrapperPrivate archive;
+ QCOMPARE(archive.isConnectedToServer(), false);
+ archive.setFilename(archiveName);
+ QCOMPARE(archive.isConnectedToServer(), true);
+
+ QVERIFY(archive.open(QIODevice::ReadWrite));
+ QVERIFY(archive.create(QStringList() << source.fileName()));
+ QVERIFY(QFileInfo::exists(archiveName));
+
+ QVERIFY(archive.extract(targetName, 1));
+ const QString sourceFilename = QFileInfo(source.fileName()).fileName();
+ QVERIFY(QFileInfo::exists(targetName + sourceFilename));
+ VerifyInstaller::verifyFileContent(targetName + sourceFilename, source.readAll());
+ archive.close();
+
+ QVERIFY(source.remove());
+ QVERIFY(QFile::remove(archiveName));
+ removeDirectory(targetName);
+#endif
+ }
+
void cleanupTestCase()
{
RemoteClient::instance().setActive(false);
diff --git a/tests/auto/installer/commandlineinstall/commandlineinstall.pro b/tests/auto/installer/commandlineinstall/commandlineinstall.pro
new file mode 100644
index 000000000..891830a97
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/commandlineinstall.pro
@@ -0,0 +1,9 @@
+include(../../qttest.pri)
+
+QT += qml
+
+SOURCES += tst_commandlineinstall.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/commandlineinstall/data/components.xml b/tests/auto/installer/commandlineinstall/data/components.xml
new file mode 100644
index 000000000..d5102787f
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/components.xml
@@ -0,0 +1,24 @@
+<Packages>
+ <ApplicationName>Online Installer Example</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Package>
+ <Name>A</Name>
+ <Title>A Title</Title>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-02-13</InstallDate>
+ <Size>74</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>B</Name>
+ <Title>B Title</Title>
+ <Description>Example component B</Description>
+ <Version>1.0.0-1</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-02-13</InstallDate>
+ <Size>74</Size>
+ <Checkable>true</Checkable>
+ </Package>
+</Packages> \ No newline at end of file
diff --git a/tests/auto/installer/commandlineinstall/data/componentsFromInstallPackagesRepository.xml b/tests/auto/installer/commandlineinstall/data/componentsFromInstallPackagesRepository.xml
new file mode 100644
index 000000000..18d6f11c3
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/componentsFromInstallPackagesRepository.xml
@@ -0,0 +1,160 @@
+<Packages>
+ <ApplicationName>Dependency Solving Example</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Package>
+ <Name>componentA</Name>
+ <Title>Component A</Title>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>158</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentB</Name>
+ <Title>Component B</Title>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentC</Name>
+ <Title>Component C (depends on A and B)</Title>
+ <Description>This component depends on Component A and Component B. Selecting this component for installation also marks Component A and Component B for installation, which in turn marks Component D, because it has an automatic dependency on Component A and Component B.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Dependencies>componentA,componentB</Dependencies>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentD</Name>
+ <Title>Component D (auto depends on A and B)</Title>
+ <Description>This component has an automatic dependency on Component A and Component B. If both A and B are marked for installation, this component is also installed.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <AutoDependOn>componentA,componentB</AutoDependOn>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentE</Name>
+ <Title>Component E (forced)</Title>
+ <Description>This is a forced component that is always installed.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <ForcedInstallation>true</ForcedInstallation>
+ </Package>
+ <Package>
+ <Name>componentF</Name>
+ <Title>Component F</Title>
+ <Description>This component contains 2 subcomponents.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentF.subcomponent1</Name>
+ <Title>Subcomponent 1</Title>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentF.subcomponent1.subsubcomponent1</Name>
+ <Title>Subsubcomponent 1</Title>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentF.subcomponent1.subsubcomponent2</Name>
+ <Title>Subsubcomponent 2</Title>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentF.subcomponent2</Name>
+ <Title>Subcomponent 2</Title>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentF.subcomponent2.subsubcomponent1</Name>
+ <Title>Subsubcomponent 1</Title>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentF.subcomponent2.subsubcomponent2</Name>
+ <Title>Subsubcomponent 2</Title>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentG</Name>
+ <Title>Component G (default, depends on A, dependency added dynamically)</Title>
+ <Description>By default, this component is selected for installation. It depends on component A. Dependency is added from inside component script.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Dependencies>componentA</Dependencies>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentH</Name>
+ <Title>Component H</Title>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <Virtual>true</Virtual>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentI</Name>
+ <Title>Component I</Title>
+ <Description>This component has an automatic dependency on Component C. If C is marked for installation, this component is also installed.</Description>
+ <Version>1.0.0</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2020-03-23</InstallDate>
+ <Size>99</Size>
+ <AutoDependOn>componentC</AutoDependOn>
+ <Virtual>true</Virtual>
+ <Checkable>true</Checkable>
+ </Package>
+</Packages>
diff --git a/tests/auto/installer/commandlineinstall/data/config.xml b/tests/auto/installer/commandlineinstall/data/config.xml
new file mode 100644
index 000000000..041ce5062
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/config.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Installer>
+ <Name>Your application</Name>
+ <Version>1.2.3</Version>
+ <MaintenanceToolName></MaintenanceToolName>
+ <MaintenanceToolIniFile></MaintenanceToolIniFile>
+ <TargetConfigurationFile></TargetConfigurationFile>
+</Installer>
diff --git a/tests/auto/installer/commandlineinstall/data/filequeryrepository/A/1.0.2-1meta.7z b/tests/auto/installer/commandlineinstall/data/filequeryrepository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..0b0b6ade6
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/filequeryrepository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/filequeryrepository/Updates.xml b/tests/auto/installer/commandlineinstall/data/filequeryrepository/Updates.xml
new file mode 100644
index 000000000..7957cde4e
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/filequeryrepository/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>A component</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>4b124046df83fcd12fb7126b795a8b5a62602806</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/Updates.xml b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/Updates.xml
new file mode 100644
index 000000000..72931954a
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/Updates.xml
@@ -0,0 +1,72 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>New dependency added</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="299" UncompressedSize="158"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>92b02a74d0886bc1569ff8b3a7edd1f9d828e56c</SHA1>
+ <Dependencies>componentF</Dependencies>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>90</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>aedfaef53cdc0f52353a8680009be405fa767811</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C. Dependencies removed</DisplayName>
+ <Description>This component dependencies on Component A and Component B are removed in update.</Description>
+ <Dependencies></Dependencies>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>20b9463a5e06f373182b3c7c4cf879806d429409</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D (auto depends on A and B)</DisplayName>
+ <Description>This component has an automatic dependency on Component A and Component B. If both A and B are marked for installation, this component is also installed.</Description>
+ <AutoDependOn>componentA, componentB</AutoDependOn>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>70</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>99cf24c71559c75dfae9933826ed16051fca6ea1</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF</Name>
+ <DisplayName>Component F</DisplayName>
+ <Description>This component contains 2 subcomponents.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e6443a8b5a5651f63c0604cae6d32431ca617f1a</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentH</Name>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Virtual>false</Virtual>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentA/2.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentA/2.0.0content.7z
new file mode 100644
index 000000000..4ddbe565b
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentA/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentB/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentB/1.0.0content.7z
new file mode 100644
index 000000000..f84ffcdc5
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentB/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentC/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentC/1.0.0content.7z
new file mode 100644
index 000000000..9ad11e06f
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentC/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentD/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentD/1.0.0content.7z
new file mode 100644
index 000000000..0c8c52e31
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentD/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentF/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentF/1.0.0content.7z
new file mode 100644
index 000000000..4a04b1394
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentF/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentH/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentH/1.0.0content.7z
new file mode 100644
index 000000000..e1449ad29
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesDependencyChanged/componentH/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml
new file mode 100644
index 000000000..3b5e22cc0
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/Updates.xml
@@ -0,0 +1,183 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="299" UncompressedSize="158"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>92b02a74d0886bc1569ff8b3a7edd1f9d828e56c</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>90</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>aedfaef53cdc0f52353a8680009be405fa767811</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C (depends on A and B)</DisplayName>
+ <Description>This component depends on Component A and Component B. Selecting this component for installation also marks Component A and Component B for installation, which in turn marks Component D, because it has an automatic dependency on Component A and Component B.</Description>
+ <Dependencies>componentA, componentB</Dependencies>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>20b9463a5e06f373182b3c7c4cf879806d429409</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D (auto depends on A and B)</DisplayName>
+ <Description>This component has an automatic dependency on Component A and Component B. If both A and B are marked for installation, this component is also installed.</Description>
+ <AutoDependOn>componentA, componentB</AutoDependOn>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>70</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>99cf24c71559c75dfae9933826ed16051fca6ea1</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentE</Name>
+ <DisplayName>Component E (forced)</DisplayName>
+ <Description>This is a forced component that is always installed.</Description>
+ <ForcedInstallation>true</ForcedInstallation>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>60</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>926bf503ccdff93351744843a95e5e2172cad5ec</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF</Name>
+ <DisplayName>Component F</DisplayName>
+ <Description>This component contains 2 subcomponents.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e6443a8b5a5651f63c0604cae6d32431ca617f1a</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>a3bc5dce1c93add30c22e46436396c66b0b51001</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="289" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>ebe4d69414a1675a7f46887e15d9bffc275b7cc4</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="289" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e4379d20320d4c173b2d8e228f5722e3f36e3114</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2</Name>
+ <DisplayName>Subcomponent 2</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6462be25912c490569a7c4f3931d978e78c69dc4</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="289" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>72b224bc8f3431210834ce6db373fc8d638a3546</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="289" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3e2744edaef06af75b3248d5935523a6e2e61551</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentG</Name>
+ <DisplayName>Component G (default, depends on A, dependency added dynamically)</DisplayName>
+ <Description>By default, this component is selected for installation. It depends on component A. Dependency is added from inside component script.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <Script>installscript.js</Script>
+ <SortingPriority>30</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>8cba36dd589492c28e0d04942b4f8aa0a09f59cc</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentH</Name>
+ <DisplayName>component H</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Virtual>true</Virtual>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentI</Name>
+ <DisplayName>component I</DisplayName>
+ <Description>This component has an automatic dependency on Component C. If C is marked for installation, this component is also installed.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <AutoDependOn>componentC</AutoDependOn>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Virtual>true</Virtual>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentJ</Name>
+ <DisplayName>component J</DisplayName>
+ <Description>This component has post install script.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Script postLoad="True">postLoadscript.js</Script>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentA/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentA/1.0.0content.7z
new file mode 100644
index 000000000..4ddbe565b
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentB/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentB/1.0.0content.7z
new file mode 100644
index 000000000..f84ffcdc5
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentB/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentC/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentC/1.0.0content.7z
new file mode 100644
index 000000000..9ad11e06f
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentC/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentD/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentD/1.0.0content.7z
new file mode 100644
index 000000000..0c8c52e31
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentD/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentE/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentE/1.0.0content.7z
new file mode 100644
index 000000000..f5abacf81
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentE/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..3aced680f
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..e5385a163
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..5bc549863
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..da9e9f340
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..d0b013706
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..74ab44033
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF/1.0.0content.7z
new file mode 100644
index 000000000..4a04b1394
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentF/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentG/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentG/1.0.0content.7z
new file mode 100644
index 000000000..81fc02052
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentG/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentG/1.0.0meta.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentG/1.0.0meta.7z
new file mode 100644
index 000000000..90bfe33a2
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentG/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentH/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentH/1.0.0content.7z
new file mode 100644
index 000000000..e1449ad29
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentH/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentI/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentI/1.0.0content.7z
new file mode 100644
index 000000000..651a29f94
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentI/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z
new file mode 100644
index 000000000..58ff52baa
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z
new file mode 100644
index 000000000..be99410a8
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/installPackagesRepository/componentJ/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineinstall/data/repository/Updates.xml b/tests/auto/installer/commandlineinstall/data/repository/Updates.xml
new file mode 100644
index 000000000..52707d09d
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/repository/Updates.xml
@@ -0,0 +1,69 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>9d54e3a5adf3563913feee8ba23a99fb80d46590</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>9170d55a6af81c1a6a63d708a4ab6ed359775cd9</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>5b3939da1af492382c68388fc796837e4c36b876</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C.virt</Name>
+ <DisplayName>Virtual subcomponent of C</DisplayName>
+ <Description>Example virtual component</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Virtual>true</Virtual>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>5b3939da1af492382c68388fc796837e4c36b876</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C.virt.subcomponent</Name>
+ <DisplayName>Subcomponent of virtual component</DisplayName>
+ <Description>Example subcomponent of virtual component</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>5b3939da1af492382c68388fc796837e4c36b876</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>AB</Name>
+ <DisplayName>AB</DisplayName>
+ <Description>Example component AB</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile UncompressedSize="0" OS="Any" CompressedSize="0"/>
+ <SHA1>f75e65b1a0f68abb77fc41da08fc26dda5409a18</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineinstall/data/uninstallableComponentsRepository/Updates.xml b/tests/auto/installer/commandlineinstall/data/uninstallableComponentsRepository/Updates.xml
new file mode 100644
index 000000000..f0c724db8
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/data/uninstallableComponentsRepository/Updates.xml
@@ -0,0 +1,50 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c1f340c9a7ad1edbef4cb6288c83c646211e5ccd</SHA1>
+ <AutoDependOn>autoDep</AutoDependOn>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>AB</Name>
+ <DisplayName>AB</DisplayName>
+ <Description>Example component AB</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+ <SHA1>3c1470896a9db84092e00806b1303f3b5fa4f7ad</SHA1>
+ <Checkable>false</Checkable>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>cfa136fa1d7a4196896c90af72d510727ba799ae</SHA1>
+ <Virtual>true</Virtual>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B.subcomponent</Name>
+ <DisplayName>Subcomponent of B</DisplayName>
+ <Description>Example non-virtual subcomponent of B</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>cfa136fa1d7a4196896c90af72d510727ba799ae</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineinstall/settings.qrc b/tests/auto/installer/commandlineinstall/settings.qrc
new file mode 100644
index 000000000..992dbfd58
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/settings.qrc
@@ -0,0 +1,37 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/config.xml</file>
+ <file>data/repository/Updates.xml</file>
+ <file>data/uninstallableComponentsRepository/Updates.xml</file>
+ <file>data/components.xml</file>
+ <file>data/installPackagesRepository/Updates.xml</file>
+ <file>data/installPackagesRepository/componentA/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentB/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentC/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentD/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentE/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentG/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentH/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentI/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentJ/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentJ/1.0.0meta.7z</file>
+ <file>data/installPackagesRepository/componentG/1.0.0meta.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesDependencyChanged/Updates.xml</file>
+ <file>data/installPackagesDependencyChanged/componentA/2.0.0content.7z</file>
+ <file>data/installPackagesDependencyChanged/componentB/1.0.0content.7z</file>
+ <file>data/installPackagesDependencyChanged/componentC/1.0.0content.7z</file>
+ <file>data/installPackagesDependencyChanged/componentD/1.0.0content.7z</file>
+ <file>data/installPackagesDependencyChanged/componentF/1.0.0content.7z</file>
+ <file>data/installPackagesDependencyChanged/componentH/1.0.0content.7z</file>
+ <file>data/filequeryrepository/Updates.xml</file>
+ <file>data/filequeryrepository/A/1.0.2-1meta.7z</file>
+ <file>data/componentsFromInstallPackagesRepository.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp b/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp
new file mode 100644
index 000000000..4dfadbad6
--- /dev/null
+++ b/tests/auto/installer/commandlineinstall/tst_commandlineinstall.cpp
@@ -0,0 +1,813 @@
+/**************************************************************************
+**
+** Copyright (C) 2024 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <component.h>
+#include <packagemanagercore.h>
+
+#include <QLoggingCategory>
+#include <QTest>
+#include <QRegularExpression>
+#include <QSignalSpy>
+
+using namespace QInstaller;
+
+typedef QList<QPair<QString, QString> > ComponentResourceHash;
+typedef QPair<QString, QString> ComponentResource;
+
+class tst_CommandLineInstall : public QObject
+{
+ Q_OBJECT
+
+public:
+ void ignoreAvailablePackagesMissingMessages()
+ {
+ QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Searching packages with regular expression:"));
+ QTest::ignoreMessage(QtDebugMsg, "No matching packages found.");
+ }
+
+ void ignoreInstallPackageFailsMessages(const QRegularExpression &regExp)
+ {
+ QTest::ignoreMessage(QtDebugMsg, "Fetching latest update information...");
+ QTest::ignoreMessage(QtDebugMsg, regExp);
+ }
+
+private slots:
+ void testListAvailablePackages()
+ {
+ QString loggingRules = (QLatin1String("ifw.* = false\n"));
+
+ QLoggingCategory::setFilterRules(loggingRules);
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager
+ (m_installDir, ":///data/repository"));
+
+ auto func = &PackageManagerCore::listAvailablePackages;
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<availablepackages>\n"
+ " <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n"
+ " <package name=\"A\" displayname=\"A\" version=\"1.0.2-1\"/>\n"
+ " <package name=\"B\" displayname=\"B\" version=\"1.0.0-1\"/>\n"
+ " <package name=\"C\" displayname=\"C\" version=\"1.0.0-1\"/>\n"
+ "</availablepackages>\n"), func, QLatin1String("."), QHash<QString, QString>());
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<availablepackages>\n"
+ " <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n"
+ " <package name=\"A\" displayname=\"A\" version=\"1.0.2-1\"/>\n"
+ "</availablepackages>\n"), func, QLatin1String("A"), QHash<QString, QString>());
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<availablepackages>\n"
+ " <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n"
+ " <package name=\"A\" displayname=\"A\" version=\"1.0.2-1\"/>\n"
+ "</availablepackages>\n"), func, QLatin1String("A.*"), QHash<QString, QString>());
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<availablepackages>\n"
+ " <package name=\"B\" displayname=\"B\" version=\"1.0.0-1\"/>\n"
+ "</availablepackages>\n"), func, QLatin1String("^B"), QHash<QString, QString>());
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<availablepackages>\n"
+ " <package name=\"B\" displayname=\"B\" version=\"1.0.0-1\"/>\n"
+ "</availablepackages>\n"), func, QLatin1String("^B.*"), QHash<QString, QString>());
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<availablepackages>\n"
+ " <package name=\"C\" displayname=\"C\" version=\"1.0.0-1\"/>\n"
+ "</availablepackages>\n"), func, QLatin1String("^C"), QHash<QString, QString>());
+
+ // Test with filters
+ QHash<QString, QString> searchHash {
+ { "Version", "1.0.2" },
+ { "DisplayName", "A" }
+ };
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<availablepackages>\n"
+ " <package name=\"AB\" displayname=\"AB\" version=\"1.0.2-1\"/>\n"
+ " <package name=\"A\" displayname=\"A\" version=\"1.0.2-1\"/>\n"
+ "</availablepackages>\n"), func, QString(), searchHash);
+
+ searchHash.clear();
+ searchHash.insert("Default", "false");
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<availablepackages>\n"
+ " <package name=\"B\" displayname=\"B\" version=\"1.0.0-1\"/>\n"
+ "</availablepackages>\n"), func, QString(), searchHash);
+
+ QLoggingCategory::setFilterRules("ifw.* = true\n");
+ ignoreAvailablePackagesMissingMessages();
+ core->listAvailablePackages(QLatin1String("C.virt"));
+
+ ignoreAvailablePackagesMissingMessages();
+ core->listAvailablePackages(QLatin1String("C.virt.subcomponent"));
+ }
+
+ void testInstallPackageFails()
+ {
+ QString loggingRules = (QLatin1String("ifw.* = false\n"
+ "ifw.installer.installlog = true\n"));
+
+ QLoggingCategory::setFilterRules(loggingRules);
+ QTest::ignoreMessage(QtDebugMsg, "Operations sanity check succeeded.");
+ QTest::ignoreMessage(QtDebugMsg, QRegularExpression("Using metadata cache from "));
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager
+ (m_installDir, ":///data/uninstallableComponentsRepository"));
+
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install component A. Component "
+ "is installed only as automatic dependency to autoDep.\n"));
+ QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
+ << QLatin1String("A")));
+
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install component AB. Component "
+ "is not checkable, meaning you have to select one of the subcomponents.\n"));
+ QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
+ << QLatin1String("AB")));
+
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install B. Component is virtual.\n"));
+ QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
+ << QLatin1String("B")));
+
+ ignoreInstallPackageFailsMessages(QRegularExpression("Cannot install B.subcomponent. Component "
+ "is a descendant of a virtual component B.\n"));
+ QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
+ << QLatin1String("B.subcomponent")));
+
+ QCOMPARE(PackageManagerCore::Canceled, core->installSelectedComponentsSilently(QStringList()
+ << QLatin1String("MissingComponent")));
+ QCOMPARE(PackageManagerCore::Canceled, core->status());
+ }
+
+ void testUninstallPackageFails()
+ {
+ QString loggingRules = (QLatin1String("ifw.installer.installog = true\n"));
+ PackageManagerCore core;
+ core.setPackageManager();
+ QLoggingCategory::setFilterRules(loggingRules);
+
+ QVERIFY(QFile::copy(":/data/componentsFromInstallPackagesRepository.xml", m_installDir + "/components.xml"));
+
+ core.setValue(scTargetDir, m_installDir);
+ QTest::ignoreMessage(QtWarningMsg, "Cannot uninstall ForcedInstallation component componentE");
+ QCOMPARE(PackageManagerCore::Success, core.uninstallComponentsSilently(QStringList()
+ << "componentE"));
+
+ QTest::ignoreMessage(QtWarningMsg, "Cannot uninstall component componentD because it is added as auto dependency to componentA,componentB");
+ QCOMPARE(PackageManagerCore::Success, core.uninstallComponentsSilently(QStringList()
+ << "componentD"));
+
+ QTest::ignoreMessage(QtWarningMsg, "Cannot uninstall component MissingComponent. Component not found in install tree.");
+ QCOMPARE(PackageManagerCore::Success, core.uninstallComponentsSilently(QStringList()
+ << "MissingComponent"));
+
+ QTest::ignoreMessage(QtWarningMsg, "Cannot uninstall virtual component componentH");
+ QCOMPARE(PackageManagerCore::Success, core.uninstallComponentsSilently(QStringList()
+ << "componentH"));
+
+ QCOMPARE(PackageManagerCore::Success, core.status());
+ }
+
+ void testListInstalledPackages()
+ {
+ QString loggingRules = (QLatin1String("ifw.* = false\n"));
+ PackageManagerCore core;
+ core.setPackageManager();
+ QLoggingCategory::setFilterRules(loggingRules);
+ auto func = &PackageManagerCore::listInstalledPackages;
+
+ const QString testDirectory = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(testDirectory));
+ QVERIFY(QFile::copy(":/data/components.xml", testDirectory + "/components.xml"));
+
+ core.setValue(scTargetDir, testDirectory);
+
+ VerifyInstaller::verifyListPackagesMessage(&core, QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<localpackages>\n"
+ " <package name=\"A\" displayname=\"A Title\" version=\"1.0.2-1\"/>\n"
+ " <package name=\"B\" displayname=\"B Title\" version=\"1.0.0-1\"/>\n"
+ "</localpackages>\n"), func, QString());
+
+ VerifyInstaller::verifyListPackagesMessage(&core, QLatin1String("<?xml version=\"1.0\"?>\n"
+ "<localpackages>\n"
+ " <package name=\"A\" displayname=\"A Title\" version=\"1.0.2-1\"/>\n"
+ "</localpackages>\n"), func, QLatin1String("A"));
+
+ QDir dir(testDirectory);
+ QVERIFY(dir.removeRecursively());
+ }
+
+ void testCategoryInstall_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QStringList>("installComponents");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+
+
+ QTest::newRow("Category installation")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentE")
+ << PackageManagerCore::Success;
+ }
+
+ void testCategoryInstall()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QStringList, installComponents);
+ QFETCH(PackageManagerCore::Status, status);
+
+
+ QString loggingRules = (QLatin1String("ifw.* = true\n"));
+ QLoggingCategory::setFilterRules(loggingRules);
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir));
+
+ RepositoryCategory category;
+ category.setEnabled(false);
+ category.setDisplayName(QLatin1String("category"));
+
+ Repository repo = Repository::fromUserInput(repository);
+ category.addRepository(repo);
+
+ QSet<RepositoryCategory> categories;
+ categories.insert(category);
+
+ core->settings().addRepositoryCategories(categories);
+
+ QSignalSpy spy(core.data(), &PackageManagerCore::statusChanged);
+ QCOMPARE(core->installSelectedComponentsSilently(QStringList() << installComponents), status);
+
+ QList<int> statusArguments;
+
+ for (qsizetype i = 0; i < spy.size(); ++i) {
+ QList<QVariant> tempList = spy.at(i);
+ statusArguments << tempList.at(0).toInt();
+ }
+
+ QVERIFY(statusArguments.contains(PackageManagerCore::NoPackagesFound));
+ QVERIFY(statusArguments.contains(PackageManagerCore::Success));
+ }
+
+ void testInstall_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QStringList>("installComponents");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+ QTest::addColumn<ComponentResourceHash>("componentResources");
+ QTest::addColumn<QStringList >("installedFiles");
+
+ /*********** Forced installation **********/
+ ComponentResourceHash componentResources;
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt")); //ForcedInstall
+ componentResources.append(ComponentResource("componentG", "1.0.0content.txt")); //Depends on componentA
+
+ QTest::newRow("Forced installation")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentE")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt");
+
+ /*********** Simple installation **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt")); //ForcedInstall
+ componentResources.append(ComponentResource("componentG", "1.0.0content.txt")); //Depends on componentA
+
+ QTest::newRow("Simple installation")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentA")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt");
+
+ /*********** Install with dependency **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt")); //Dependency for componentC
+ componentResources.append(ComponentResource("componentB", "1.0.0content.txt")); //Dependency for componentC
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt")); //ForcedInstall
+ componentResources.append(ComponentResource("componentG", "1.0.0content.txt")); //Depends on componentA
+ componentResources.append(ComponentResource("componentI", "1.0.0content.txt")); //Virtual, depends on componentC
+ componentResources.append(ComponentResource("componentD", "1.0.0content.txt")); //Autodepend on componentA and componentB
+
+ QTest::newRow("Install with dependency")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentC")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontentC.txt"
+ << "installcontent.txt" << "installcontentA.txt" << "installcontentB.txt"
+ << "installcontentD.txt"<< "installcontentE.txt" << "installcontentG.txt"
+ << "installcontentI.txt");
+
+ /*********** Install with subcomponents **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("componentF.subcomponent2.subsubcomponent2", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF.subcomponent2", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt")); //Dependency for componentG
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt")); //ForcedInstall
+ componentResources.append(ComponentResource("componentG", "1.0.0content.txt")); //Default install
+
+ QTest::newRow("Install with subcomponents")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentF.subcomponent2.subsubcomponent2")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontentF.txt"
+ << "installcontentF_2.txt" << "installcontentF_2_2.txt"
+ << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentE.txt" << "installcontentG.txt");
+ }
+
+ void testInstall()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QStringList, installComponents);
+ QFETCH(PackageManagerCore::Status, status);
+ QFETCH(ComponentResourceHash, componentResources);
+ QFETCH(QStringList, installedFiles);
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, repository));
+
+ QCOMPARE(status, core->installSelectedComponentsSilently(QStringList() << installComponents));
+ for (const ComponentResource &resource : componentResources)
+ VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second);
+ VerifyInstaller::verifyFileExistence(m_installDir, installedFiles);
+ }
+
+ void testUninstall_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QStringList>("installComponents");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+ QTest::addColumn<ComponentResourceHash>("componentResources");
+ QTest::addColumn<QStringList >("installedFiles");
+ QTest::addColumn<QStringList>("uninstallComponents");
+ QTest::addColumn<PackageManagerCore::Status>("uninstallStatus");
+ QTest::addColumn<ComponentResourceHash>("componentResourcesAfterUninstall");
+ QTest::addColumn<QStringList >("installedFilesAfterUninstall");
+ QTest::addColumn<ComponentResourceHash >("deletedComponentResources");
+ QTest::addColumn<bool >("virtualSetVisible");
+
+ /*********** Uninstallation **********/
+ ComponentResourceHash componentResourcesAfterUninstall;
+ componentResourcesAfterUninstall.append(ComponentResource("componentE", "1.0.0content.txt")); //ForcedInstall
+
+ ComponentResourceHash deletedComponentResources;
+ deletedComponentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentG", "1.0.0content.txt"));
+
+ ComponentResourceHash componentResourceAfterInstall;
+ componentResourceAfterInstall << deletedComponentResources << componentResourcesAfterUninstall;
+
+ QStringList filesAfterUninstall;
+ filesAfterUninstall << "components.xml" << "installcontentE.txt";
+
+ QStringList filesAfterInstall;
+ filesAfterInstall << filesAfterUninstall << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentG.txt";
+
+ QTest::newRow("Test uninstall")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentA")
+ << PackageManagerCore::Success
+ << componentResourceAfterInstall
+ << filesAfterInstall
+ << (QStringList() << "componentA")
+ << PackageManagerCore::Success
+ << componentResourcesAfterUninstall
+ << filesAfterUninstall
+ << deletedComponentResources;
+
+ /*********** Uninstall with dependency **********/
+ componentResourcesAfterUninstall.clear();
+ componentResourcesAfterUninstall.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResourcesAfterUninstall.append(ComponentResource("componentB", "1.0.0content.txt"));
+ componentResourcesAfterUninstall.append(ComponentResource("componentE", "1.0.0content.txt"));
+ componentResourcesAfterUninstall.append(ComponentResource("componentG", "1.0.0content.txt"));
+ componentResourcesAfterUninstall.append(ComponentResource("componentD", "1.0.0content.txt"));
+
+ deletedComponentResources.clear();
+ deletedComponentResources.append(ComponentResource("componentC", "1.0.0content.txt")); //Unselected
+ deletedComponentResources.append(ComponentResource("componentI", "1.0.0content.txt")); //Autodepends on componentC
+
+ componentResourceAfterInstall.clear();
+ componentResourceAfterInstall << deletedComponentResources << componentResourcesAfterUninstall;
+
+ filesAfterUninstall.clear();
+ filesAfterUninstall << "components.xml"
+ << "installcontent.txt" << "installcontentA.txt" << "installcontentB.txt"
+ << "installcontentD.txt"<< "installcontentE.txt" << "installcontentG.txt";
+
+ filesAfterInstall.clear();
+ filesAfterInstall << filesAfterUninstall << "installcontentC.txt"
+ << "installcontentI.txt";
+
+
+ QTest::newRow("Uninstall with dependency")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentC")
+ << PackageManagerCore::Success
+ << componentResourceAfterInstall
+ << filesAfterInstall
+ << (QStringList() << "componentC")
+ << PackageManagerCore::Success
+ << componentResourcesAfterUninstall
+ << filesAfterUninstall
+ << deletedComponentResources;
+
+ /*********** Uninstall with subcomponents **********/
+ componentResourcesAfterUninstall.clear();
+ componentResourcesAfterUninstall.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResourcesAfterUninstall.append(ComponentResource("componentE", "1.0.0content.txt"));
+ componentResourcesAfterUninstall.append(ComponentResource("componentG", "1.0.0content.txt"));
+
+ deletedComponentResources.clear();
+ deletedComponentResources.append(ComponentResource("componentF.subcomponent2.subsubcomponent2", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentF.subcomponent2", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentF", "1.0.0content.txt"));
+
+ componentResourceAfterInstall.clear();
+ componentResourceAfterInstall << deletedComponentResources << componentResourcesAfterUninstall;
+
+ filesAfterInstall.clear();
+ filesAfterInstall << "components.xml" << "installcontentF.txt"
+ << "installcontentF_2.txt" << "installcontentF_2_2.txt"
+ << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentE.txt" << "installcontentG.txt";
+
+ filesAfterUninstall.clear();
+ filesAfterUninstall << "components.xml"
+ << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentE.txt" << "installcontentG.txt";
+
+ QTest::newRow("Uninstall with subcomponents")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentF.subcomponent2.subsubcomponent2")
+ << PackageManagerCore::Success
+ << componentResourceAfterInstall
+ << filesAfterInstall
+ << (QStringList() << "componentF.subcomponent2")
+ << PackageManagerCore::Success
+ << componentResourcesAfterUninstall
+ << filesAfterUninstall
+ << deletedComponentResources;
+
+ /*********** Uninstall forced packages **********/
+ componentResourceAfterInstall.clear();
+ componentResourceAfterInstall.append(ComponentResource("componentA", "1.0.0content.txt")); //ComponentG depends
+ componentResourceAfterInstall.append(ComponentResource("componentE", "1.0.0content.txt")); //ForcedInstall
+ componentResourceAfterInstall.append(ComponentResource("componentG", "1.0.0content.txt")); //Default
+
+ componentResourcesAfterUninstall.clear();
+ componentResourcesAfterUninstall = componentResourceAfterInstall; //forced packages cannot be uninstalled
+
+ deletedComponentResources.clear();
+
+ filesAfterInstall.clear();
+ filesAfterInstall << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt";
+
+ filesAfterUninstall.clear();
+ filesAfterUninstall = filesAfterInstall;
+
+ QTest::newRow("Uninstall forced packages")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentG")
+ << PackageManagerCore::Success
+ << componentResourceAfterInstall
+ << filesAfterInstall
+ << (QStringList() << "componentE")
+ << PackageManagerCore::Success
+ << componentResourceAfterInstall
+ << filesAfterUninstall
+ << deletedComponentResources;
+
+ /*********** Uninstall autodependency packages **********/
+ componentResourceAfterInstall.clear();
+ componentResourceAfterInstall.append(ComponentResource("componentA", "1.0.0content.txt")); //ComponentG depends
+ componentResourceAfterInstall.append(ComponentResource("componentB", "1.0.0content.txt")); //Dependency for componentC
+ componentResourceAfterInstall.append(ComponentResource("componentD", "1.0.0content.txt")); //Autodepend on componentA and componentB
+ componentResourceAfterInstall.append(ComponentResource("componentE", "1.0.0content.txt")); //ForcedInstall
+ componentResourceAfterInstall.append(ComponentResource("componentG", "1.0.0content.txt")); //Default
+
+ componentResourcesAfterUninstall.clear();
+ componentResourcesAfterUninstall = componentResourceAfterInstall; //autodependency packages cannot be uninstalled
+
+ deletedComponentResources.clear();
+
+ filesAfterInstall.clear();
+ filesAfterInstall << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt"
+ << "installcontentB.txt" << "installcontentD.txt";
+ filesAfterUninstall.clear();
+ filesAfterUninstall = filesAfterInstall;
+
+ QTest::newRow("Uninstall autodependency packages")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentA" << "componentB")
+ << PackageManagerCore::Success
+ << componentResourceAfterInstall
+ << filesAfterInstall
+ << (QStringList() << "componentD")
+ << PackageManagerCore::Success
+ << componentResourceAfterInstall
+ << filesAfterUninstall
+ << deletedComponentResources;
+ }
+
+ void testUninstall()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QStringList, installComponents);
+ QFETCH(PackageManagerCore::Status, status);
+ QFETCH(ComponentResourceHash, componentResources);
+ QFETCH(QStringList, installedFiles);
+ QFETCH(QStringList, uninstallComponents);
+ QFETCH(PackageManagerCore::Status, uninstallStatus);
+ QFETCH(ComponentResourceHash, componentResourcesAfterUninstall);
+ QFETCH(QStringList, installedFilesAfterUninstall);
+ QFETCH(ComponentResourceHash, deletedComponentResources);
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, repository));
+
+ QCOMPARE(status, core->installSelectedComponentsSilently(QStringList() << installComponents));
+ for (const ComponentResource &resource : componentResources)
+ VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second);
+ VerifyInstaller::verifyFileExistence(m_installDir, installedFiles);
+ core->commitSessionOperations();
+ core->setPackageManager();
+
+ QCOMPARE(uninstallStatus, core->uninstallComponentsSilently(QStringList()
+ << uninstallComponents));
+ QCOMPARE(uninstallStatus, core->status());
+ for (const ComponentResource &resource : componentResourcesAfterUninstall)
+ VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second);
+ for (const ComponentResource &resource : deletedComponentResources)
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, resource.first, resource.second);
+ VerifyInstaller::verifyFileExistence(m_installDir, installedFilesAfterUninstall);
+ }
+
+ void addToExistingInstall_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QStringList>("installComponents");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+ QTest::addColumn<ComponentResourceHash>("componentResources");
+ QTest::addColumn<QStringList >("installedFiles");
+ QTest::addColumn<QString>("newRepository");
+ QTest::addColumn<QStringList>("installNewComponents");
+ QTest::addColumn<PackageManagerCore::Status>("reinstallStatus");
+ QTest::addColumn<ComponentResourceHash>("componentResourcesAfterReinstall");
+ QTest::addColumn<QStringList >("installedFilesAfterReinstall");
+ QTest::addColumn<ComponentResourceHash >("deletedComponentResources");
+
+ /*********** New dependency in repository **********/
+ ComponentResourceHash componentResourceAfterInstall;
+ componentResourceAfterInstall.append(ComponentResource("componentA", "1.0.0content.txt")); //ComponentC depends on
+ componentResourceAfterInstall.append(ComponentResource("componentB", "1.0.0content.txt")); //ComponentC depends on
+ componentResourceAfterInstall.append(ComponentResource("componentC", "1.0.0content.txt")); //Selected
+ componentResourceAfterInstall.append(ComponentResource("componentD", "1.0.0content.txt")); //Autodepend on componentA,componentB
+ componentResourceAfterInstall.append(ComponentResource("componentE", "1.0.0content.txt")); //Forced
+ componentResourceAfterInstall.append(ComponentResource("componentG", "1.0.0content.txt")); //Default
+ componentResourceAfterInstall.append(ComponentResource("componentI", "1.0.0content.txt")); //Autodepend componentC
+
+ ComponentResourceHash componentResourcesAfterReinstall;
+ componentResourcesAfterReinstall = componentResourceAfterInstall;
+ componentResourcesAfterReinstall.append(ComponentResource("componentH", "1.0.0content.txt"));
+
+ ComponentResourceHash deletedComponentResources;
+ // New dependency is added in repository from componentA to componentF, check that it is not installed
+ deletedComponentResources.append(ComponentResource("componentF", "1.0.0content.txt"));
+
+ QStringList filesAfterInstall;
+ filesAfterInstall << "components.xml"
+ << "installcontent.txt" << "installcontentA.txt" << "installcontentB.txt"
+ << "installcontentC.txt" << "installcontentD.txt" << "installcontentE.txt"
+ << "installcontentG.txt" << "installcontentI.txt";
+
+ QStringList filesAfterReinstall;
+ filesAfterReinstall = filesAfterInstall;
+ filesAfterReinstall << "installcontentH.txt";
+
+ QTest::newRow("New dependency in repository")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentC")
+ << PackageManagerCore::Success
+ << componentResourceAfterInstall
+ << filesAfterInstall
+ << ":///data/installPackagesDependencyChanged"
+ << (QStringList() << "componentH")
+ << PackageManagerCore::Success
+ << componentResourcesAfterReinstall
+ << filesAfterReinstall
+ << deletedComponentResources;
+ }
+
+ void addToExistingInstall()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QStringList, installComponents);
+ QFETCH(PackageManagerCore::Status, status);
+ QFETCH(ComponentResourceHash, componentResources);
+ QFETCH(QStringList, installedFiles);
+ QFETCH(QString, newRepository);
+ QFETCH(QStringList, installNewComponents);
+ QFETCH(PackageManagerCore::Status, reinstallStatus);
+ QFETCH(ComponentResourceHash, componentResourcesAfterReinstall);
+ QFETCH(QStringList, installedFilesAfterReinstall);
+ QFETCH(ComponentResourceHash, deletedComponentResources);
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, repository));
+ QCOMPARE(status, core->installSelectedComponentsSilently(installComponents));
+ QCOMPARE(status, core->status());
+
+ for (const ComponentResource &resource : componentResources)
+ VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second);
+ VerifyInstaller::verifyFileExistence(m_installDir, installedFiles);
+
+ core->reset();
+ core->cancelMetaInfoJob(); //Call cancel to reset metadata so that update repositories are fetched
+
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(newRepository);
+ repoList.insert(repo);
+ core->settings().setDefaultRepositories(repoList);
+
+ QCOMPARE(reinstallStatus, core->installSelectedComponentsSilently(installNewComponents));
+
+ for (const ComponentResource &resource : deletedComponentResources)
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, resource.first, resource.second);
+ for (const ComponentResource &resource : componentResourcesAfterReinstall)
+ VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second);
+ VerifyInstaller::verifyFileExistence(m_installDir, installedFilesAfterReinstall);
+ }
+
+ void testInstallDefaultPackagesSilently()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository"));
+ QCOMPARE(PackageManagerCore::Success, core->installDefaultComponentsSilently());
+ QCOMPARE(PackageManagerCore::Success, core->status());
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA", "1.0.0content.txt"); //Dependency for componentG
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentE", "1.0.0content.txt"); //ForcedInstall
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentG", "1.0.0content.txt"); //Default
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt");
+ }
+
+
+ void testNoDefaultInstallations()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository"));
+ core->setNoDefaultInstallation(true);
+ QCOMPARE(PackageManagerCore::Success, core->installDefaultComponentsSilently());
+ QCOMPARE(PackageManagerCore::Success, core->status());
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "installcontentE.txt");
+ core->setNoDefaultInstallation(false);
+ }
+
+ void testRemoveAllSilently()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList()
+ << QLatin1String("componentA")));
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml" << "installcontentE.txt"
+ << "installcontentA.txt" << "installcontent.txt" << "installcontentG.txt");
+
+ core->commitSessionOperations();
+ core->setUninstaller();
+ QCOMPARE(PackageManagerCore::Success, core->removeInstallationSilently());
+ QCOMPARE(PackageManagerCore::Success, core->status());
+ VerifyInstaller::verifyInstallerResourcesDeletion(m_installDir, "componentA");
+ VerifyInstaller::verifyInstallerResourcesDeletion(m_installDir, "componentE");
+ VerifyInstaller::verifyInstallerResourcesDeletion(m_installDir, "componentG");
+
+ // On Windows we have to settle for the resources check above as maintenance
+ // tool (if it would exists) and target directory are only removed later via
+ // started VBScript process. On Unix platforms the target directory should
+ // be removed in PackageManagerCorePrivate::runUninstaller().
+#if defined(Q_OS_UNIX)
+ QVERIFY(!QDir(m_installDir).exists());
+#endif
+ }
+
+ void testUninstallVirtualSetVisibleSilently()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository"));
+ core->setVirtualComponentsVisible(true);
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList()
+ <<"componentH"));
+ QCOMPARE(PackageManagerCore::Success, core->status());
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentH", "1.0.0content.txt");
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ QCOMPARE(PackageManagerCore::Success, core->uninstallComponentsSilently(QStringList()
+ << "componentH"));
+ QCOMPARE(PackageManagerCore::Success, core->status());
+ VerifyInstaller::verifyInstallerResourcesDeletion(m_installDir, "componentH");
+ }
+
+ void testFileQuery()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit(m_installDir,
+ ":///data/filequeryrepository"));
+ core->setCommandLineInstance(true);
+ core->setFileDialogAutomaticAnswer("ValidDirectory", m_installDir);
+
+ QString testFile = qApp->applicationDirPath() + QDir::toNativeSeparators("/test");
+ QFile file(testFile);
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ core->setFileDialogAutomaticAnswer("ValidFile", testFile);
+
+ //File dialog launched without ID
+ core->setFileDialogAutomaticAnswer("GetExistingDirectory", m_installDir);
+ core->setFileDialogAutomaticAnswer("GetExistingFile", testFile);
+
+ QCOMPARE(PackageManagerCore::Success, core->installDefaultComponentsSilently());
+ QCOMPARE(PackageManagerCore::Success, core->status());
+
+ QVERIFY(core->containsFileDialogAutomaticAnswer("ValidFile"));
+ core->removeFileDialogAutomaticAnswer("ValidFile");
+ QVERIFY(!core->containsFileDialogAutomaticAnswer("ValidFile"));
+
+ QVERIFY(file.remove());
+ }
+
+ void testPostScript()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << QLatin1String("componentJ")));
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentJ", "1.0.0content.txt"); //Selected
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA", "1.0.0content.txt"); //Dependency for componentG
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentE", "1.0.0content.txt"); //ForcedInstall
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentG", "1.0.0content.txt"); //Default
+
+ //componentJ is extracted to "extractToAnotherPath" -folder in post install script
+ bool fileExists = QFileInfo::exists(m_installDir + QDir::separator() + "extractToAnotherPath" + QDir::separator() + "installcontentJ.txt");
+ QVERIFY2(fileExists, QString("File \"%1\" does not exist.").arg("installcontentJ.txt").toLatin1());
+ }
+
+ void init()
+ {
+ m_installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_installDir));
+ }
+
+ void initTestCase()
+ {
+ qSetGlobalQHashSeed(0); //Ensures the dom document deterministic behavior
+ }
+
+ void cleanup()
+ {
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
+private:
+ QString m_installDir;
+};
+
+
+QTEST_MAIN(tst_CommandLineInstall)
+
+#include "tst_commandlineinstall.moc"
diff --git a/tests/auto/installer/commandlineupdate/commandlineupdate.pro b/tests/auto/installer/commandlineupdate/commandlineupdate.pro
new file mode 100644
index 000000000..543ec8b23
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/commandlineupdate.pro
@@ -0,0 +1,9 @@
+include(../../qttest.pri)
+
+QT += qml
+
+SOURCES += tst_commandlineupdate.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/commandlineupdate/data/config.xml b/tests/auto/installer/commandlineupdate/data/config.xml
new file mode 100644
index 000000000..041ce5062
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/config.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Installer>
+ <Name>Your application</Name>
+ <Version>1.2.3</Version>
+ <MaintenanceToolName></MaintenanceToolName>
+ <MaintenanceToolIniFile></MaintenanceToolIniFile>
+ <TargetConfigurationFile></TargetConfigurationFile>
+</Installer>
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml
new file mode 100644
index 000000000..de6e66525
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/Updates.xml
@@ -0,0 +1,179 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="299" UncompressedSize="158"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>92b02a74d0886bc1569ff8b3a7edd1f9d828e56c</SHA1>
+ <Essential>true</Essential>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>90</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>aedfaef53cdc0f52353a8680009be405fa767811</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C (depends on A and B)</DisplayName>
+ <Description>This component depends on Component A and Component B. Selecting this component for installation also marks Component A and Component B for installation, which in turn marks Component D, because it has an automatic dependency on Component A and Component B.</Description>
+ <Dependencies>componentA, componentB</Dependencies>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>20b9463a5e06f373182b3c7c4cf879806d429409</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D (auto depends on A and B)</DisplayName>
+ <Description>This component has an automatic dependency on Component A and Component B. If both A and B are marked for installation, this component is also installed.</Description>
+ <AutoDependOn>componentA, componentB</AutoDependOn>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>70</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>99cf24c71559c75dfae9933826ed16051fca6ea1</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentE</Name>
+ <DisplayName>Component E (forced)</DisplayName>
+ <Description>This is a forced component that is always installed.</Description>
+ <ForcedInstallation>true</ForcedInstallation>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>60</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>926bf503ccdff93351744843a95e5e2172cad5ec</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF</Name>
+ <DisplayName>Component F</DisplayName>
+ <Description>This component contains 2 subcomponents.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e6443a8b5a5651f63c0604cae6d32431ca617f1a</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>a3bc5dce1c93add30c22e46436396c66b0b51001</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="289" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>ebe4d69414a1675a7f46887e15d9bffc275b7cc4</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="289" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e4379d20320d4c173b2d8e228f5722e3f36e3114</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2</Name>
+ <DisplayName>Subcomponent 2</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6462be25912c490569a7c4f3931d978e78c69dc4</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="289" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>72b224bc8f3431210834ce6db373fc8d638a3546</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="289" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3e2744edaef06af75b3248d5935523a6e2e61551</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentG</Name>
+ <DisplayName>Component G (default, depends on A, dependency added dynamically)</DisplayName>
+ <Description>By default, this component is selected for installation. It depends on component A. Dependency is added from inside component script.</Description>
+ <Default>true</Default>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <Script>installscript.js</Script>
+ <SortingPriority>30</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="281" UncompressedSize="99"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>8cba36dd589492c28e0d04942b4f8aa0a09f59cc</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentH</Name>
+ <DisplayName>Component H. ForcedUpdate</DisplayName>
+ <Description>Component H. ForcedUpdate</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <ForcedUpdate>true</ForcedUpdate>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>qt.tools.qtcreator</Name>
+ <DisplayName>Component qtcreator. Depends on virtual component</DisplayName>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <Dependencies>qt.tools.qtcreator.enterprise.plugins</Dependencies>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>qt.tools.qtcreator.enterprise.plugins</Name>
+ <DisplayName>enterprise plugin component</DisplayName>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Virtual>true</Virtual>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentA/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentA/1.0.0content.7z
new file mode 100644
index 000000000..4ddbe565b
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentB/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentB/1.0.0content.7z
new file mode 100644
index 000000000..f84ffcdc5
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentB/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentC/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentC/1.0.0content.7z
new file mode 100644
index 000000000..9ad11e06f
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentC/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentD/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentD/1.0.0content.7z
new file mode 100644
index 000000000..0c8c52e31
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentD/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentE/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentE/1.0.0content.7z
new file mode 100644
index 000000000..f5abacf81
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentE/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..3aced680f
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..e5385a163
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..5bc549863
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..da9e9f340
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..d0b013706
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..74ab44033
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF/1.0.0content.7z
new file mode 100644
index 000000000..4a04b1394
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentF/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentG/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentG/1.0.0content.7z
new file mode 100644
index 000000000..81fc02052
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentG/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentG/1.0.0meta.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentG/1.0.0meta.7z
new file mode 100644
index 000000000..e5c446f64
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentG/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7z
new file mode 100644
index 000000000..e1449ad29
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/componentH/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7z
new file mode 100644
index 000000000..5c7c4f37d
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7z
new file mode 100644
index 000000000..e5e4178a4
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml
new file mode 100644
index 000000000..5fbfaa5e9
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/Updates.xml
@@ -0,0 +1,163 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>43c8fcc544ea6d35fe5180a50d4764dcf9fd7473</SHA1>
+ <Essential>true</Essential>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>90</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c360591443f4f46c14cd05b0e7f93a105857b563</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C (depends on A and B)</DisplayName>
+ <Description>This component depends on Component A and Component B. Selecting this component for installation also marks Component A and Component B for installation, which in turn marks Component D, because it has an automatic dependency on Component A and Component B.</Description>
+ <Dependencies>componentA, componentB</Dependencies>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3c5acf95ad15a2ea6e2baaf55dd79053ca439668</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D (auto depends on A and B)</DisplayName>
+ <Description>This component has an automatic dependency on Component A and Component B. If both A and B are marked for installation, this component is also installed.</Description>
+ <AutoDependOn>componentA, componentB</AutoDependOn>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>70</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>5b014c99bf083377024f3de42553faad0c69ebbb</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentE</Name>
+ <DisplayName>Component E (forced)</DisplayName>
+ <Description>This is a forced component that is always installed.</Description>
+ <ForcedInstallation>true</ForcedInstallation>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>60</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>bf312c4593abaa8f6d18a1504c411e5ec8130860</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF</Name>
+ <DisplayName>Component F</DisplayName>
+ <Description>This component contains 2 subcomponents.</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>d8764d228cc32be0959b286cf57a30252082d2dc</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="281" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>fbdd255c25820331ffea46c9a80905580fb8ad4f</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="289" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c96ddbefa66f5a3400e0c2f3a458c0f619d99690</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile CompressedSize="289" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c88f52f11f22089d7efc3b65394e96ee1656702e</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2</Name>
+ <DisplayName>Subcomponent 2</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>57120d69b22e013666b80d3954b1ee65eb37891f</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="289" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3844dc1b4805050f34b483661843a8f8a4e97864</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile CompressedSize="289" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e1d988818cb8fd89e8863b5699b19823e38f0919</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentG</Name>
+ <DisplayName>Component G (default, depends on A, dependency added dynamically)</DisplayName>
+ <Description>By default, this component is selected for installation. It depends on component A. Dependency is added from inside component script.</Description>
+ <Default>true</Default>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <Script>installscript.js</Script>
+ <SortingPriority>30</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>098b5ecafe8853371fd608acd9b1ccab252ef5df</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentH</Name>
+ <DisplayName>Component H. ForcedUpdate</DisplayName>
+ <Description>Component H. ForcedUpdate</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <ForcedUpdate>true</ForcedUpdate>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentA/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentA/1.0.0content.7z
new file mode 100644
index 000000000..4ddbe565b
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentA/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentA/2.0.0content.7z
new file mode 100644
index 000000000..9e947f5f7
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentA/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentB/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentB/2.0.0content.7z
new file mode 100644
index 000000000..08f7ad70d
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentB/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentC/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentC/2.0.0content.7z
new file mode 100644
index 000000000..3cd9e94fe
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentC/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentD/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentD/2.0.0content.7z
new file mode 100644
index 000000000..992b756d2
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentD/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentE/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentE/2.0.0content.7z
new file mode 100644
index 000000000..d6e7562b1
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentE/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..b559dd72f
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..a2109e812
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..55655d1d3
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..c469c39a9
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..164348ac9
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2/2.0.0content.7z
new file mode 100644
index 000000000..921c501cd
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF.subcomponent2/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF/2.0.0content.7z
new file mode 100644
index 000000000..6973624df
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentF/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentG/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentG/2.0.0content.7z
new file mode 100644
index 000000000..a3d72046e
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentG/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentG/2.0.0meta.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentG/2.0.0meta.7z
new file mode 100644
index 000000000..a34fd36f1
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentG/2.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/1.0.0content.7z
new file mode 100644
index 000000000..e1449ad29
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7z
new file mode 100644
index 000000000..f74b8da68
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdate/componentH/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/Updates.xml b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/Updates.xml
new file mode 100644
index 000000000..f56888022
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/Updates.xml
@@ -0,0 +1,163 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>43c8fcc544ea6d35fe5180a50d4764dcf9fd7473</SHA1>
+ <Essential>true</Essential>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>90</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c360591443f4f46c14cd05b0e7f93a105857b563</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C (depends on A and B)</DisplayName>
+ <Description>This component depends on Component A and Component B. Selecting this component for installation also marks Component A and Component B for installation, which in turn marks Component D, because it has an automatic dependency on Component A and Component B.</Description>
+ <Dependencies>componentA, componentB</Dependencies>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3c5acf95ad15a2ea6e2baaf55dd79053ca439668</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D (auto depends on A and B)</DisplayName>
+ <Description>This component has an automatic dependency on Component A and Component B. If both A and B are marked for installation, this component is also installed.</Description>
+ <AutoDependOn>componentA, componentB</AutoDependOn>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>70</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>5b014c99bf083377024f3de42553faad0c69ebbb</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentE</Name>
+ <DisplayName>Component E (forced)</DisplayName>
+ <Description>This is a forced component that is always installed.</Description>
+ <ForcedInstallation>true</ForcedInstallation>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>60</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>bf312c4593abaa8f6d18a1504c411e5ec8130860</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF</Name>
+ <DisplayName>Component F</DisplayName>
+ <Description>This component contains 2 subcomponents.</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>d8764d228cc32be0959b286cf57a30252082d2dc</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="281" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>fbdd255c25820331ffea46c9a80905580fb8ad4f</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="289" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c96ddbefa66f5a3400e0c2f3a458c0f619d99690</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile CompressedSize="289" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c88f52f11f22089d7efc3b65394e96ee1656702e</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2</Name>
+ <DisplayName>Subcomponent 2</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>57120d69b22e013666b80d3954b1ee65eb37891f</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="289" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3844dc1b4805050f34b483661843a8f8a4e97864</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile CompressedSize="289" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e1d988818cb8fd89e8863b5699b19823e38f0919</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentG</Name>
+ <DisplayName>Component G (default, depends on A, dependency added dynamically)</DisplayName>
+ <Description>By default, this component is selected for installation. It depends on component A. Dependency is added from inside component script.</Description>
+ <Default>true</Default>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <Script>installscript.js</Script>
+ <SortingPriority>30</SortingPriority>
+ <UpdateFile CompressedSize="297" UncompressedSize="99" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>098b5ecafe8853371fd608acd9b1ccab252ef5df</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentH</Name>
+ <DisplayName>Component H. ForcedUpdate</DisplayName>
+ <Description>Component H. ForcedUpdate</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <ForcedUpdate>true</ForcedUpdate>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentA/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentA/2.0.0content.7z
new file mode 100644
index 000000000..9e947f5f7
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentA/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentB/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentB/2.0.0content.7z
new file mode 100644
index 000000000..08f7ad70d
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentB/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentC/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentC/2.0.0content.7z
new file mode 100644
index 000000000..3cd9e94fe
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentC/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentD/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentD/2.0.0content.7z
new file mode 100644
index 000000000..992b756d2
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentD/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentE/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentE/2.0.0content.7z
new file mode 100644
index 000000000..d6e7562b1
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentE/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..b559dd72f
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..a2109e812
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..55655d1d3
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..c469c39a9
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..164348ac9
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2/2.0.0content.7z
new file mode 100644
index 000000000..921c501cd
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF/2.0.0content.7z
new file mode 100644
index 000000000..6973624df
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentF/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0content.7z
new file mode 100644
index 000000000..a3d72046e
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0meta.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0meta.7z
new file mode 100644
index 000000000..a34fd36f1
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentH/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentH/2.0.0content.7z
new file mode 100644
index 000000000..f74b8da68
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/installPackagesRepositoryUpdateWithEssential/componentH/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/Updates.xml b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/Updates.xml
new file mode 100644
index 000000000..f55998c48
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/Updates.xml
@@ -0,0 +1,32 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>qt.tools.qtcreator</Name>
+ <DisplayName>Component qtcreator. Dependency removed</DisplayName>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>qt.tools.qtcreator_gui</Name>
+ <DisplayName>Component K. Autodepends on componentJ</DisplayName>
+ <Description>Component K. Autodepends on componentJ</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <AutoDependOn>qt.tools.qtcreator</AutoDependOn>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>qt.tools.qtcreator_gui.enterprise.plugins</Name>
+ <DisplayName>enterprise plugins, replaces another component</DisplayName>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2018-03-14</ReleaseDate>
+ <Virtual>true</Virtual>
+ <Replaces>qt.tools.qtcreator.enterprise.plugins</Replaces>
+ <AutoDependOn>qt.tools.qtcreator</AutoDependOn>
+ <UpdateFile UncompressedSize="99" OS="Any" CompressedSize="305"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7z
new file mode 100644
index 000000000..f2b69fc13
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7z
new file mode 100644
index 000000000..03d191cb5
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7z b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7z
new file mode 100644
index 000000000..515c3a5cf
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/Updates.xml b/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/Updates.xml
new file mode 100644
index 000000000..1729f5732
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/Updates.xml
@@ -0,0 +1,26 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>3.0.0</Version>
+ <ReleaseDate>2015-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <Essential>true</Essential>
+ <UpdateFile UncompressedSize="99" OS="Any" CompressedSize="297"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentAutoDependOnA</Name>
+ <DisplayName>Component, autodepends on A</DisplayName>
+ <Description>Component, autodepends on A</Description>
+ <Version>1.0</Version>
+ <ReleaseDate>2018-03-14</ReleaseDate>
+ <AutoDependOn>componentA</AutoDependOn>
+ <UpdateFile UncompressedSize="99" OS="Any" CompressedSize="305"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/componentA/3.0.0content.7z b/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/componentA/3.0.0content.7z
new file mode 100644
index 000000000..e8c35fdea
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/componentA/3.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/componentAutoDependOnA/1.0content.7z b/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/componentAutoDependOnA/1.0content.7z
new file mode 100644
index 000000000..0f3b123e0
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/data/repositoryWithDependencyToEssential/componentAutoDependOnA/1.0content.7z
Binary files differ
diff --git a/tests/auto/installer/commandlineupdate/settings.qrc b/tests/auto/installer/commandlineupdate/settings.qrc
new file mode 100644
index 000000000..c8f328d6b
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/settings.qrc
@@ -0,0 +1,62 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/config.xml</file>
+ <file>data/installPackagesRepository/Updates.xml</file>
+ <file>data/installPackagesRepository/componentA/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentB/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentC/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentD/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentE/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentG/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentG/1.0.0meta.7z</file>
+ <file>data/installPackagesRepository/componentH/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/qt.tools.qtcreator/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/qt.tools.qtcreator.enterprise.plugins/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/Updates.xml</file>
+ <file>data/installPackagesRepositoryUpdate/componentA/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentB/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentC/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentD/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentE/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentF/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentG/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentG/2.0.0meta.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentH/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentF.subcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentF.subcomponent2/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdate/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/Updates.xml</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentA/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentB/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentC/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentD/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentE/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentF/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentG/2.0.0meta.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentH/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2/2.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/installPackagesRepositoryUpdateWithEssential/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/repositoryWithDependencyToEssential/Updates.xml</file>
+ <file>data/repositoryWithDependencyToEssential/componentAutoDependOnA/1.0content.7z</file>
+ <file>data/repositoryWithDependencyToEssential/componentA/3.0.0content.7z</file>
+ <file>data/repositoryUpdateWithReplacements/Updates.xml</file>
+ <file>data/repositoryUpdateWithReplacements/qt.tools.qtcreator/2.0.0content.7z</file>
+ <file>data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui/2.0.0content.7z</file>
+ <file>data/repositoryUpdateWithReplacements/qt.tools.qtcreator_gui.enterprise.plugins/2.0.0content.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp b/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp
new file mode 100644
index 000000000..0faeecf74
--- /dev/null
+++ b/tests/auto/installer/commandlineupdate/tst_commandlineupdate.cpp
@@ -0,0 +1,418 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <component.h>
+#include <packagemanagercore.h>
+
+#include <QLoggingCategory>
+#include <QTest>
+
+using namespace QInstaller;
+
+typedef QList<QPair<QString, QString> > ComponentResourceHash;
+typedef QPair<QString, QString> ComponentResource;
+
+class tst_CommandLineUpdate : public QObject
+{
+ Q_OBJECT
+
+private:
+ void setRepository(const QString &repository, PackageManagerCore *core)
+ {
+ core->reset();
+ core->cancelMetaInfoJob(); //Call cancel to reset metadata so that update repositories are fetched
+
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(repository);
+ repoList.insert(repo);
+ core->settings().setDefaultRepositories(repoList);
+ }
+
+private slots:
+
+ void testUpdate_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QStringList>("installComponents");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+ QTest::addColumn<ComponentResourceHash>("componentResources");
+ QTest::addColumn<QStringList >("installedFiles");
+ QTest::addColumn<QString>("updateRepository");
+ QTest::addColumn<QStringList>("updateComponents");
+ QTest::addColumn<PackageManagerCore::Status>("updateStatus");
+ QTest::addColumn<ComponentResourceHash>("componentResourcesAfterUpdate");
+ QTest::addColumn<QStringList >("installedFilesAfterUpdate");
+ QTest::addColumn<ComponentResourceHash >("deletedComponentResources");
+
+ /*********** Update essential packages **********/
+ ComponentResourceHash componentResources;
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+
+ ComponentResourceHash componentResourcesAfterUpdate;
+ componentResourcesAfterUpdate.append(ComponentResource("componentA", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentE", "1.0.0content.txt"));
+
+ ComponentResourceHash deletedComponentResources;
+ deletedComponentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+
+ QTest::newRow("Update essential packages")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentA")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt")
+ << ":///data/installPackagesRepositoryUpdateWithEssential"
+ << (QStringList() << "componentB")
+ << PackageManagerCore::EssentialUpdated
+ << componentResourcesAfterUpdate
+ << (QStringList() << "components.xml"
+ << "installcontentA_update.txt" << "installcontentE.txt" << "installcontentG.txt")
+ << deletedComponentResources;
+
+ /*********** Update essential with autodependon**********/
+ componentResourcesAfterUpdate.clear();
+ componentResourcesAfterUpdate.append(ComponentResource("componentA", "3.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentAutoDependOnA", "1.0content.txt"));
+
+ QTest::newRow("Update essential with autodependon")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentA")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt")
+ << ":///data/repositoryWithDependencyToEssential"
+ << (QStringList())
+ << PackageManagerCore::EssentialUpdated
+ << componentResourcesAfterUpdate
+ << (QStringList() << "components.xml"
+ << "installcontentA_update.txt" << "installcontentE.txt" << "installcontentG.txt"
+ << "installContentAutoDependOnA.txt")
+ << deletedComponentResources;
+
+
+ /*********** Update force update packages **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("componentH", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+
+ componentResourcesAfterUpdate.clear();
+ componentResourcesAfterUpdate.append(ComponentResource("componentH", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentE", "1.0.0content.txt"));
+
+ deletedComponentResources.clear();
+ deletedComponentResources.append(ComponentResource("componentH", "1.0.0content.txt"));
+
+ QTest::newRow("Update force update packages")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentH")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt"
+ << "installcontentH.txt")
+ << ":///data/installPackagesRepositoryUpdateWithEssential"
+ << (QStringList())
+ << PackageManagerCore::EssentialUpdated
+ << componentResourcesAfterUpdate
+ << (QStringList() << "components.xml" << "installcontentA_update.txt"
+ << "installcontentE.txt" << "installcontentG.txt"
+ << "installcontentH_update.txt")
+ << deletedComponentResources;
+
+ /*********** Update packages **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentB", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentD", "1.0.0content.txt"));
+
+ componentResourcesAfterUpdate.clear();
+ componentResourcesAfterUpdate.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentB", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentD", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentE", "2.0.0content.txt"));
+
+ deletedComponentResources.clear();
+ deletedComponentResources.append(ComponentResource("componentB", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentD", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+
+ QTest::newRow("Update packages")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentC" << "componentH")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentB.txt" << "installcontentC.txt" << "installcontentD.txt"
+ << "installcontentE.txt" << "installcontentG.txt" << "installcontentH.txt")
+ << ":///data/installPackagesRepositoryUpdate"
+ << (QStringList())
+ << PackageManagerCore::Success
+ << componentResourcesAfterUpdate
+ << (QStringList() << "components.xml" << "installcontent.txt"
+ << "installcontentA.txt" << "installcontentB_update.txt" << "installcontentC_update.txt" << "installcontentD_update.txt"
+ << "installcontentE_update.txt" << "installcontentG_update.txt" << "installcontentH.txt")
+ << deletedComponentResources;
+
+ /*********** Update two packages **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentB", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentD", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentG", "1.0.0content.txt"));
+
+ componentResourcesAfterUpdate.clear();
+ componentResourcesAfterUpdate.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentB", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentD", "1.0.0content.txt"));//AutodepenOn componentA,componentB
+ componentResourcesAfterUpdate.append(ComponentResource("componentE", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentG", "2.0.0content.txt"));
+
+ deletedComponentResources.clear();
+ deletedComponentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentG", "1.0.0content.txt"));
+
+ QTest::newRow("Update two packages")
+ << ":///data/installPackagesRepository"
+ << (QStringList()<< "componentA" << "componentB" << "componentE" << "componentG")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentD.txt" << "installcontentB.txt" << "installcontentE.txt"
+ << "installcontentG.txt")
+ << ":///data/installPackagesRepositoryUpdate"
+ << (QStringList() << "componentE" << "componentG")
+ << PackageManagerCore::Success
+ << componentResourcesAfterUpdate
+ << (QStringList() << "components.xml" << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentD.txt" << "installcontentB.txt"
+ << "installcontentE_update.txt" << "installcontentG_update.txt")
+ << deletedComponentResources;
+
+ /*********** Update all packages **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentB", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentC", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentD", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF.subcomponent1", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF.subcomponent1.subsubcomponent1", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF.subcomponent1.subsubcomponent2", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF.subcomponent2", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF.subcomponent2.subsubcomponent1", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentF.subcomponent2.subsubcomponent2", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentG", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentH", "1.0.0content.txt"));
+
+ componentResourcesAfterUpdate.clear();
+ componentResourcesAfterUpdate.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentB", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentC", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentD", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentE", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentF", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentF.subcomponent1", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentF.subcomponent1.subsubcomponent1", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentF.subcomponent1.subsubcomponent2", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentF.subcomponent2", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentF.subcomponent2.subsubcomponent1", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentF.subcomponent2.subsubcomponent2", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentG", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentH", "1.0.0content.txt"));
+
+ deletedComponentResources.clear();
+ deletedComponentResources.append(ComponentResource("componentB", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentD", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentF", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentF.subcomponent2", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentG", "1.0.0content.txt"));
+
+ QTest::newRow("Update all packages")
+ << ":///data/installPackagesRepository"
+ << (QStringList() << "componentA" << "componentB" << "componentC" << "componentD" << "componentE"
+ << "componentF" << "componentG" << "componentH")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentB.txt" << "installcontentC.txt" << "installcontentD.txt"
+ << "installcontentE.txt" << "installcontentF.txt" << "installcontentF_1.txt" << "installcontentF_1_1.txt"
+ << "installcontentF_1_2.txt" << "installcontentF_2.txt" << "installcontentF_2_1.txt" << "installcontentF_2_2.txt"
+ << "installcontentG.txt" << "installcontentH.txt")
+ << ":///data/installPackagesRepositoryUpdate"
+ << (QStringList())
+ << PackageManagerCore::Success
+ << componentResourcesAfterUpdate
+ << (QStringList() << "components.xml" << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentB_update.txt" << "installcontentC_update.txt" << "installcontentD_update.txt"
+ << "installcontentE_update.txt" << "installcontentF_update.txt" << "installcontentF_1.txt" << "installcontentF_1_1.txt"
+ << "installcontentF_1_2.txt" << "installcontentF_2_update.txt" << "installcontentF_2_1.txt" << "installcontentF_2_2.txt"
+ << "installcontentG_update.txt" << "installcontentH.txt")
+ << deletedComponentResources;
+
+ /*********** Update packages with AutoDependOn **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentB", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentD", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentG", "1.0.0content.txt"));
+
+ componentResourcesAfterUpdate.clear();
+ componentResourcesAfterUpdate.append(ComponentResource("componentA", "1.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentB", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentD", "2.0.0content.txt"));//AutodepenOn componentA,componentB
+ componentResourcesAfterUpdate.append(ComponentResource("componentE", "1.0.0content.txt"));//ForcedInstall, not updated without user selection
+ componentResourcesAfterUpdate.append(ComponentResource("componentG", "1.0.0content.txt"));
+
+ deletedComponentResources.clear();
+ deletedComponentResources.append(ComponentResource("componentB", "1.0.0content.txt"));
+ deletedComponentResources.append(ComponentResource("componentD", "1.0.0content.txt"));
+
+ QTest::newRow("Update packages with AutoDependOn")
+ << ":///data/installPackagesRepository"
+ << (QStringList()<< "componentA" << "componentB" << "componentE" << "componentG")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentD.txt" << "installcontentB.txt" << "installcontentE.txt"
+ << "installcontentG.txt")
+ << ":///data/installPackagesRepositoryUpdate"
+ << (QStringList() << "componentB")
+ << PackageManagerCore::Success
+ << componentResourcesAfterUpdate
+ << (QStringList() << "components.xml" << "installcontent.txt" << "installcontentA.txt"
+ << "installcontentD_update.txt" << "installcontentB_update.txt"
+ << "installcontentE.txt" << "installcontentG.txt")
+ << deletedComponentResources;
+
+ /*********** Update packages with replacements **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("qt.tools.qtcreator", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("qt.tools.qtcreator.enterprise.plugins", "1.0.0content.txt"));
+ componentResources.append(ComponentResource("componentE", "1.0.0content.txt"));
+
+ componentResourcesAfterUpdate.clear();
+ componentResourcesAfterUpdate.append(ComponentResource("qt.tools.qtcreator", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("qt.tools.qtcreator_gui", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("qt.tools.qtcreator_gui.enterprise.plugins", "2.0.0content.txt"));
+ componentResourcesAfterUpdate.append(ComponentResource("componentE", "1.0.0content.txt"));
+
+ deletedComponentResources.clear();
+ deletedComponentResources.append(ComponentResource("qt.tools.qtcreator.enterprise.plugins", "1.0.0content.txt"));
+
+ QTest::newRow("Update packages with replacements")
+ << ":///data/installPackagesRepository"
+ << (QStringList()<< "qt.tools.qtcreator")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt"
+ << "installcontent.txt" << "qtcreator.txt" << "plugins.txt")
+ << ":///data/repositoryUpdateWithReplacements"
+ << (QStringList() << "qt.tools.qtcreator")
+ << PackageManagerCore::Success
+ << componentResourcesAfterUpdate
+ << (QStringList() << "components.xml" << "installcontentA.txt" << "installcontentE.txt" << "installcontentG.txt"
+ << "installcontent.txt" << "gui.txt" << "qtcreator2.txt" << "gui_plugins.txt")
+ << deletedComponentResources;
+ }
+
+ void testUpdate()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QStringList, installComponents);
+ QFETCH(PackageManagerCore::Status, status);
+ QFETCH(ComponentResourceHash, componentResources);
+ QFETCH(QStringList, installedFiles);
+ QFETCH(QString, updateRepository);
+ QFETCH(QStringList, updateComponents);
+ QFETCH(PackageManagerCore::Status, updateStatus);
+ QFETCH(ComponentResourceHash, componentResourcesAfterUpdate);
+ QFETCH(QStringList, installedFilesAfterUpdate);
+ QFETCH(ComponentResourceHash, deletedComponentResources);
+
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit(m_installDir, repository);
+
+ QCOMPARE(status, core->installSelectedComponentsSilently(QStringList() << installComponents));
+ for (const ComponentResource &resource : componentResources) {
+ VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second);
+ }
+ VerifyInstaller::verifyFileExistence(m_installDir, installedFiles);
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ setRepository(updateRepository, core);
+ QCOMPARE(updateStatus, core->updateComponentsSilently(updateComponents));
+
+ for (const ComponentResource &resource : componentResourcesAfterUpdate) {
+ VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second);
+ }
+ for (const ComponentResource &resource : deletedComponentResources) {
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, resource.first, resource.second);
+ }
+ VerifyInstaller::verifyFileExistence(m_installDir, installedFilesAfterUpdate);
+ delete core;
+ }
+
+ void testUpdateNoUpdatesForSelectedPackage()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepositoryUpdate"));
+ // No updates available for component so nothing to do
+ QCOMPARE(PackageManagerCore::Canceled, core->updateComponentsSilently(QStringList()
+ << "componentInvalid"));
+ }
+
+ void init()
+ {
+ m_installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_installDir));
+ }
+
+ void cleanup()
+ {
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
+private:
+ QString m_installDir;
+};
+
+
+QTEST_MAIN(tst_CommandLineUpdate)
+
+#include "tst_commandlineupdate.moc"
diff --git a/tests/auto/installer/componentalias/componentalias.pro b/tests/auto/installer/componentalias/componentalias.pro
new file mode 100644
index 000000000..efbc0268f
--- /dev/null
+++ b/tests/auto/installer/componentalias/componentalias.pro
@@ -0,0 +1,8 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_componentalias.cpp
+
+RESOURCES += settings.qrc
diff --git a/tests/auto/installer/componentalias/data/aliases-optional.xml b/tests/auto/installer/componentalias/data/aliases-optional.xml
new file mode 100644
index 000000000..2016592c1
--- /dev/null
+++ b/tests/auto/installer/componentalias/data/aliases-optional.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Aliases>
+ <Alias>
+ <Name>set-A</Name>
+ <DisplayName>Installation A (optional component requirement)</DisplayName>
+ <Description>Installs component A</Description>
+ <Version>2.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>A</RequiredComponents>
+ <OptionalComponents>component-nonexistent,B</OptionalComponents>
+ </Alias>
+ <Alias>
+ <Name>set-full</Name>
+ <DisplayName>Full installation (optional alias requirement)</DisplayName>
+ <Description>Installs all components</Description>
+ <Version>2.0.0</Version>
+ <Virtual>false</Virtual>
+ <OptionalAliases>set-A,set-nonexistent</OptionalAliases>
+ </Alias>
+ <Alias>
+ <Name>set-optional-broken</Name>
+ <DisplayName>Optionally requires broken alias</DisplayName>
+ <Description>Optionally requires broken alias</Description>
+ <Version>2.0.0</Version>
+ <Virtual>false</Virtual>
+ <OptionalAliases>set-broken</OptionalAliases>
+ </Alias>
+ <Alias>
+ <Name>set-broken</Name>
+ <DisplayName>Requires non-existent alias</DisplayName>
+ <Description>Requires non-existent alias</Description>
+ <Version>2.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredAliases>set-nonexistent</RequiredAliases>
+ </Alias>
+ <Alias>
+ <Name>set-optional-broken-component</Name>
+ <DisplayName>Dependency to optional unstable component</DisplayName>
+ <Description>Dependency to optional unstable component</Description>
+ <Version>2.0.0</Version>
+ <Virtual>false</Virtual>
+ <OptionalComponents>UnstableComponent</OptionalComponents>
+ </Alias>
+</Aliases>
diff --git a/tests/auto/installer/componentalias/data/aliases-priority.xml b/tests/auto/installer/componentalias/data/aliases-priority.xml
new file mode 100644
index 000000000..f90d006b2
--- /dev/null
+++ b/tests/auto/installer/componentalias/data/aliases-priority.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Aliases>
+ <Alias>
+ <Name>set-A</Name>
+ <DisplayName>Installation A (priority)</DisplayName>
+ <Description>Installs component A</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>A</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-B</Name>
+ <DisplayName>Virtual installation B (priority)</DisplayName>
+ <Description>Installs component B</Description>
+ <Version>1.0.0</Version>
+ <Virtual>true</Virtual>
+ <RequiredComponents>B</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-D</Name>
+ <DisplayName>Installation D (Unstable) (priority)</DisplayName>
+ <Description>Installs missing component D</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>D</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-full</Name>
+ <DisplayName>Full installation (priority)</DisplayName>
+ <Description>Installs all components</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredAliases>set-A,set-B</RequiredAliases>
+ <RequiredComponents>C</RequiredComponents>
+ </Alias>
+</Aliases>
diff --git a/tests/auto/installer/componentalias/data/aliases-versions.xml b/tests/auto/installer/componentalias/data/aliases-versions.xml
new file mode 100644
index 000000000..993e14673
--- /dev/null
+++ b/tests/auto/installer/componentalias/data/aliases-versions.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Aliases>
+ <Alias>
+ <Name>set-A</Name>
+ <DisplayName>Installation A (updated)</DisplayName>
+ <Description>Installs component A</Description>
+ <Version>2.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>A</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-B</Name>
+ <DisplayName>Virtual installation B (updated)</DisplayName>
+ <Description>Installs component B</Description>
+ <Version>1.1.0</Version>
+ <Virtual>true</Virtual>
+ <RequiredComponents>B</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-D</Name>
+ <DisplayName>Installation D (Unstable) (updated)</DisplayName>
+ <Description>Installs missing component D</Description>
+ <Version>1.2.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>D</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-full</Name>
+ <DisplayName>Full installation (updated)</DisplayName>
+ <Description>Installs all components</Description>
+ <Version>3.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredAliases>set-A,set-B</RequiredAliases>
+ <RequiredComponents>C</RequiredComponents>
+ </Alias>
+</Aliases>
diff --git a/tests/auto/installer/componentalias/data/aliases.json b/tests/auto/installer/componentalias/data/aliases.json
new file mode 100644
index 000000000..4c78e20d2
--- /dev/null
+++ b/tests/auto/installer/componentalias/data/aliases.json
@@ -0,0 +1,38 @@
+{
+ "alias-packages": [
+ {
+ "Description": "Installs component A",
+ "DisplayName": "Installation A (JSON)",
+ "Name": "set-A-json",
+ "RequiredComponents": [
+ "A"
+ ],
+ "Version": "1.0.0",
+ "Virtual": false
+ },
+ {
+ "Description": "Installs component B",
+ "DisplayName": "Virtual installation B (JSON)",
+ "Name": "set-B-json",
+ "RequiredComponents": [
+ "B"
+ ],
+ "Version": "1.0.0",
+ "Virtual": true
+ },
+ {
+ "Description": "Installs all components",
+ "DisplayName": "Full installation (JSON)",
+ "Name": "set-full-json",
+ "RequiredAliases": [
+ "set-A-json",
+ "set-B-json"
+ ],
+ "RequiredComponents": [
+ "C"
+ ],
+ "Version": "1.0.0",
+ "Virtual": false
+ }
+ ]
+}
diff --git a/tests/auto/installer/componentalias/data/repository/Updates.xml b/tests/auto/installer/componentalias/data/repository/Updates.xml
new file mode 100644
index 000000000..64950244f
--- /dev/null
+++ b/tests/auto/installer/componentalias/data/repository/Updates.xml
@@ -0,0 +1,51 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C.subcomponent</Name>
+ <DisplayName>Subcomponent of C</DisplayName>
+ <Description>Example subcomponent</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C.subcomponent.subcomponent</Name>
+ <DisplayName>Subcomponent of subcomponent component</DisplayName>
+ <Description>Example subcomponent of subcomponent</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>UnstableComponent</Name>
+ <DisplayName>Subcomponent of subcomponent component</DisplayName>
+ <Description>Example subcomponent of subcomponent</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Dependencies>missing.component</Dependencies>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/componentalias/metadata/installer-config/aliases.xml b/tests/auto/installer/componentalias/metadata/installer-config/aliases.xml
new file mode 100644
index 000000000..2362e51c7
--- /dev/null
+++ b/tests/auto/installer/componentalias/metadata/installer-config/aliases.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Aliases>
+ <Alias>
+ <Name>set-A</Name>
+ <DisplayName>Installation A</DisplayName>
+ <Description>Installs component A</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>A</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-B</Name>
+ <DisplayName>Virtual installation B</DisplayName>
+ <Description>Installs component B</Description>
+ <Version>1.0.0</Version>
+ <Virtual>true</Virtual>
+ <RequiredComponents>B</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-D</Name>
+ <DisplayName>Installation D (Unstable)</DisplayName>
+ <Description>Installs missing component D</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>D</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-E</Name>
+ <DisplayName>Installation E (Requires unstable)</DisplayName>
+ <Description>Installs set E</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredAliases>set-D</RequiredAliases>
+ </Alias>
+ <Alias>
+ <Name>set-F</Name>
+ <DisplayName>Installation F (Requires alias that refers another unstable)</DisplayName>
+ <Description>Installs set F</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredAliases>set-E</RequiredAliases>
+ </Alias>
+ <Alias>
+ <Name>set-full</Name>
+ <DisplayName>Full installation</DisplayName>
+ <Description>Installs all components</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredAliases>set-A,set-B</RequiredAliases>
+ <RequiredComponents>C</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-required-component-from-fallback</Name>
+ <DisplayName>Installation (fetches component from fallback repository)</DisplayName>
+ <Description>Installs component</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>A</RequiredComponents>
+ </Alias>
+ <Alias>
+ <Name>set-optional-component-from-fallback</Name>
+ <DisplayName>Installation (fetches optional component from fallback repository)</DisplayName>
+ <Description>Installs component</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <OptionalComponents>A</OptionalComponents>
+ </Alias>
+ <Alias>
+ <Name>set-optional-broken-component-from-fallback</Name>
+ <DisplayName>Installation (fetches optional component from fallback repository)</DisplayName>
+ <Description>Installs component</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <OptionalComponents>UnstableComponent</OptionalComponents>
+ </Alias>
+ <Alias>
+ <Name>set-required-broken-component-from-fallback</Name>
+ <DisplayName>Installation (fetches optional component from fallback repository)</DisplayName>
+ <Description>Installs component</Description>
+ <Version>1.0.0</Version>
+ <Virtual>false</Virtual>
+ <RequiredComponents>UnstableComponent</RequiredComponents>
+ </Alias>
+</Aliases>
diff --git a/tests/auto/installer/componentalias/metadata/installer-config/config.xml b/tests/auto/installer/componentalias/metadata/installer-config/config.xml
new file mode 100644
index 000000000..9e2b5af55
--- /dev/null
+++ b/tests/auto/installer/componentalias/metadata/installer-config/config.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Installer>
+ <Name>test</Name>
+ <Version>1.0.0</Version>
+ <AliasDefinitionsFile>aliases.xml</AliasDefinitionsFile>
+</Installer>
diff --git a/tests/auto/installer/componentalias/settings.qrc b/tests/auto/installer/componentalias/settings.qrc
new file mode 100644
index 000000000..771586edd
--- /dev/null
+++ b/tests/auto/installer/componentalias/settings.qrc
@@ -0,0 +1,11 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/aliases.json</file>
+ <file>data/aliases-priority.xml</file>
+ <file>data/aliases-versions.xml</file>
+ <file>data/aliases-optional.xml</file>
+ <file>metadata/installer-config/config.xml</file>
+ <file>metadata/installer-config/aliases.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/componentalias/tst_componentalias.cpp b/tests/auto/installer/componentalias/tst_componentalias.cpp
new file mode 100644
index 000000000..51f6ca635
--- /dev/null
+++ b/tests/auto/installer/componentalias/tst_componentalias.cpp
@@ -0,0 +1,433 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <packagemanagercore.h>
+#include <componentalias.h>
+
+#include <QTest>
+#include <QLoggingCategory>
+
+using namespace QInstaller;
+
+class tst_ComponentAlias : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void init()
+ {
+ m_installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_installDir));
+ m_fallbackRepositoryData = QLatin1String("========================================\n"
+ "Name: set-optional-broken-component-from-fallback\n"
+ "Display name: Installation (fetches optional component from fallback repository)\n"
+ "Description: Installs component\n"
+ "Version: 1.0.0\n"
+ "Components: \n"
+ "Required aliases: \n"
+ "Optional components: UnstableComponent\n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-optional-component-from-fallback\n"
+ "Display name: Installation (fetches optional component from fallback repository)\n"
+ "Description: Installs component\n"
+ "Version: 1.0.0\nComponents: \n"
+ "Required aliases: \n"
+ "Optional components: A\n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-required-broken-component-from-fallback\n"
+ "Display name: Installation (fetches optional component from fallback repository)\n"
+ "Description: Installs component\n"
+ "Version: 1.0.0\n"
+ "Components: UnstableComponent\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-required-component-from-fallback\n"
+ "Display name: Installation (fetches component from fallback repository)\n"
+ "Description: Installs component\n"
+ "Version: 1.0.0\nComponents: A\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n");
+ }
+
+ void cleanup()
+ {
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
+ void testSearchAlias()
+ {
+ QString loggingRules = (QLatin1String("ifw.* = false\n"));
+
+ QLoggingCategory::setFilterRules(loggingRules);
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager
+ (m_installDir, ":///data/repository"));
+
+ core->setCommandLineInstance(true);
+
+ auto listMethod = &PackageManagerCore::listAvailableAliases;
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("\n"
+ "Name: set-A\n"
+ "Display name: Installation A\n"
+ "Description: Installs component A\n"
+ "Version: 1.0.0\n"
+ "Components: A\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-D\n"
+ "Display name: Installation D (Unstable)\n"
+ "Description: Installs missing component D\n"
+ "Version: 1.0.0\nComponents: D\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-E\n"
+ "Display name: Installation E (Requires unstable)\n"
+ "Description: Installs set E\nVersion: 1.0.0\nComponents: \n"
+ "Required aliases: set-D\n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-F\n"
+ "Display name: Installation F (Requires alias that refers another unstable)\n"
+ "Description: Installs set F\n"
+ "Version: 1.0.0\n"
+ "Components: \n"
+ "Required aliases: set-E\nOptional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-full\n"
+ "Display name: Full installation\n"
+ "Description: Installs all components\n"
+ "Version: 1.0.0\n"
+ "Components: C\n"
+ "Required aliases: set-A,set-B\n"
+ "Optional components: \n"
+ "Optional aliases: \n") + m_fallbackRepositoryData, listMethod, QString());
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("\n"
+ "Name: set-A\n"
+ "Display name: Installation A\n"
+ "Description: Installs component A\n"
+ "Version: 1.0.0\n"
+ "Components: A\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n"), listMethod, QLatin1String("-A"));
+ }
+
+ void testAliasSourceWithPriority()
+ {
+ QString loggingRules = (QLatin1String("ifw.* = false\n"));
+
+ QLoggingCategory::setFilterRules(loggingRules);
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager
+ (m_installDir, ":///data/repository"));
+
+ core->setCommandLineInstance(true);
+ core->addAliasSource(AliasSource(AliasSource::SourceFileFormat::Xml,
+ ":///data/aliases-priority.xml", 1));
+
+ auto listMethod = &PackageManagerCore::listAvailableAliases;
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("\n"
+ "Name: set-A\n"
+ "Display name: Installation A (priority)\n"
+ "Description: Installs component A\n"
+ "Version: 1.0.0\n"
+ "Components: A\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-D\n"
+ "Display name: Installation D (Unstable) (priority)\n"
+ "Description: Installs missing component D\n"
+ "Version: 1.0.0\n"
+ "Components: D\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-E\n"
+ "Display name: Installation E (Requires unstable)\n"
+ "Description: Installs set E\n"
+ "Version: 1.0.0\n"
+ "Components: \n"
+ "Required aliases: set-D\n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-F\n"
+ "Display name: Installation F (Requires alias that refers another unstable)\n"
+ "Description: Installs set F\n"
+ "Version: 1.0.0\n"
+ "Components: \n"
+ "Required aliases: set-E\n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-full\n"
+ "Display name: Full installation (priority)\n"
+ "Description: Installs all components\n"
+ "Version: 1.0.0\n"
+ "Components: C\n"
+ "Required aliases: set-A,set-B\n"
+ "Optional components: \n"
+ "Optional aliases: \n") + m_fallbackRepositoryData, listMethod, QString());
+ }
+
+ void testAliasSourceWithVersionCompare()
+ {
+ QString loggingRules = (QLatin1String("ifw.* = false\n"));
+
+ QLoggingCategory::setFilterRules(loggingRules);
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManager
+ (m_installDir, ":///data/repository"));
+
+ core->setCommandLineInstance(true);
+ core->addAliasSource(AliasSource(AliasSource::SourceFileFormat::Xml,
+ ":///data/aliases-versions.xml", -1));
+
+ auto listMethod = &PackageManagerCore::listAvailableAliases;
+
+ VerifyInstaller::verifyListPackagesMessage(core.get(), QLatin1String("\n"
+ "Name: set-A\n"
+ "Display name: Installation A (updated)\n"
+ "Description: Installs component A\n"
+ "Version: 2.0.0\n"
+ "Components: A\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-D\n"
+ "Display name: Installation D (Unstable) (updated)\n"
+ "Description: Installs missing component D\n"
+ "Version: 1.2.0\n"
+ "Components: D\n"
+ "Required aliases: \n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-E\n"
+ "Display name: Installation E (Requires unstable)\n"
+ "Description: Installs set E\n"
+ "Version: 1.0.0\n"
+ "Components: \n"
+ "Required aliases: set-D\n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-F\n"
+ "Display name: Installation F (Requires alias that refers another unstable)\n"
+ "Description: Installs set F\n"
+ "Version: 1.0.0\n"
+ "Components: \n"
+ "Required aliases: set-E\n"
+ "Optional components: \n"
+ "Optional aliases: \n"
+ "========================================\n"
+ "Name: set-full\n"
+ "Display name: Full installation (updated)\n"
+ "Description: Installs all components\n"
+ "Version: 3.0.0\n"
+ "Components: C\n"
+ "Required aliases: set-A,set-B\n"
+ "Optional components: \n"
+ "Optional aliases: \n") + m_fallbackRepositoryData, listMethod, QString());
+ }
+
+ void testInstallAlias_data()
+ {
+ QTest::addColumn<AliasSource>("additionalSource");
+ QTest::addColumn<QStringList>("selectedAliases");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+ QTest::addColumn<QStringList>("installedComponents");
+
+ QTest::newRow("Simple alias")
+ << AliasSource()
+ << (QStringList() << "set-A")
+ << PackageManagerCore::Success
+ << (QStringList() << "A");
+
+ QTest::newRow("Alias with dependencies")
+ << AliasSource()
+ << (QStringList() << "set-full")
+ << PackageManagerCore::Success
+ << (QStringList() << "A" << "B" << "C" << "C.subcomponent" << "C.subcomponent.subcomponent");
+
+ QTest::newRow("Alias with dependencies (JSON source)")
+ << AliasSource(AliasSource::SourceFileFormat::Json, ":///data/aliases.json", -1)
+ << (QStringList() << "set-full-json")
+ << PackageManagerCore::Success
+ << (QStringList() << "A" << "B" << "C" << "C.subcomponent" << "C.subcomponent.subcomponent");
+
+ QTest::newRow("Alias with optional components (existent and non-existent)")
+ << AliasSource(AliasSource::SourceFileFormat::Xml, ":///data/aliases-optional.xml", -1)
+ << (QStringList() << "set-A")
+ << PackageManagerCore::Success
+ << (QStringList() << "A" << "B");
+
+ QTest::newRow("Alias with optional aliases (existent and non-existent)")
+ << AliasSource(AliasSource::SourceFileFormat::Xml, ":///data/aliases-optional.xml", -1)
+ << (QStringList() << "set-full")
+ << PackageManagerCore::Success
+ << (QStringList() << "A" << "B");
+
+ QTest::newRow("Alias with optional broken alias (will install)")
+ << AliasSource(AliasSource::SourceFileFormat::Xml, ":///data/aliases-optional.xml", -1)
+ << (QStringList() << "set-optional-broken")
+ << PackageManagerCore::Success
+ << QStringList();
+
+ QTest::newRow("Alias with optional broken component (will install)")
+ << AliasSource(AliasSource::SourceFileFormat::Xml, ":///data/aliases-optional.xml", -1)
+ << (QStringList() << "set-optional-broken-component")
+ << PackageManagerCore::Success
+ << QStringList();
+ }
+
+ void testInstallAlias()
+ {
+ QFETCH(AliasSource, additionalSource);
+ QFETCH(QStringList, selectedAliases);
+ QFETCH(PackageManagerCore::Status, status);
+ QFETCH(QStringList, installedComponents);
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository"));
+
+ core->setCommandLineInstance(true);
+
+ if (!additionalSource.filename.isEmpty())
+ core->addAliasSource(additionalSource);
+ core->settings().setAllowUnstableComponents(true);
+ QCOMPARE(core->installSelectedComponentsSilently(selectedAliases), status);
+
+ for (const QString &component : installedComponents)
+ QVERIFY(core->componentByName(component)->isInstalled());
+ }
+
+ void testInstallAliasFails_data()
+ {
+ QTest::addColumn<QStringList>("selectedAliases");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+
+ QTest::newRow("Virtual alias")
+ << (QStringList() << "set-B")
+ << PackageManagerCore::Canceled;
+
+ QTest::newRow("Unstable alias")
+ << (QStringList() << "set-D")
+ << PackageManagerCore::Canceled;
+
+ QTest::newRow("Nested reference to unstable alias")
+ << (QStringList() << "set-F")
+ << PackageManagerCore::Canceled;
+ }
+
+ void testInstallAliasFails()
+ {
+ QFETCH(QStringList, selectedAliases);
+ QFETCH(PackageManagerCore::Status, status);
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository"));
+
+ core->setCommandLineInstance(true);
+
+ QCOMPARE(core->installSelectedComponentsSilently(selectedAliases), status);
+ }
+
+ void testInstallAliasWithFallbackRepositories_data()
+ {
+ QTest::addColumn<QStringList>("selectedAliases");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+ QTest::addColumn<QStringList>("installedComponents");
+
+ QTest::newRow("Component from fallback")
+ << (QStringList() << "set-required-component-from-fallback")
+ << PackageManagerCore::Success
+ << (QStringList() << "A");
+ QTest::newRow("Optional component from fallback")
+ << (QStringList() << "set-optional-component-from-fallback")
+ << PackageManagerCore::Success
+ << (QStringList() << "A");
+ QTest::newRow("Optional broken component from fallback")
+ << (QStringList() << "set-optional-broken-component-from-fallback")
+ << PackageManagerCore::Success
+ << (QStringList());
+ QTest::newRow("Required broke component from fallback")
+ << (QStringList() << "set-required-broken-component-from-fallback")
+ << PackageManagerCore::Canceled
+ << (QStringList());
+ }
+
+ void testInstallAliasWithFallbackRepositories()
+ {
+ QFETCH(QStringList, selectedAliases);
+ QFETCH(PackageManagerCore::Status, status);
+ QFETCH(QStringList, installedComponents);
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit(m_installDir));
+
+ core->setCommandLineInstance(true);
+ core->settings().setAllowUnstableComponents(true);
+ QSet<RepositoryCategory> repositoryCategories;
+ RepositoryCategory repositoryCategory;
+ repositoryCategory.setEnabled(false);
+ repositoryCategory.addRepository(Repository::fromUserInput(":///data/repository"));
+ repositoryCategories.insert(repositoryCategory);
+ core->settings().addRepositoryCategories(repositoryCategories);
+ QCOMPARE(core->installSelectedComponentsSilently(selectedAliases), status);
+
+ for (const QString &component : installedComponents)
+ QVERIFY(core->componentByName(component)->isInstalled());
+ }
+
+private:
+ QString m_installDir;
+ QString m_fallbackRepositoryData;
+};
+
+QTEST_GUILESS_MAIN(tst_ComponentAlias)
+
+#include "tst_componentalias.moc"
diff --git a/tests/auto/installer/componentmodel/data/updates.xml b/tests/auto/installer/componentmodel/data/updates.xml
index 2341866ee..cc2da0f8e 100644
--- a/tests/auto/installer/componentmodel/data/updates.xml
+++ b/tests/auto/installer/componentmodel/data/updates.xml
@@ -8,6 +8,8 @@
<DisplayName xml:lang="ru_RU">Корневая компонента</DisplayName>
<DisplayName xml:lang="de_DE">Wurzel Komponente</DisplayName>
<Description>Install this example.</Description>
+ <Description xml:lang="ru_RU">Установите этот пример.</Description>
+ <Description xml:lang="de_DE">Installieren Sie dieses Beispiel.</Description>
<Version>0.1.0-1</Version>
<ReleaseDate>2010-09-21</ReleaseDate>
<Default>true</Default>
@@ -177,4 +179,14 @@
file="license.txt"/>
</Licenses>
</PackageUpdate>
+ <PackageUpdate>
+ <Name>com.vendor.fifth.product.noncheckable.sub2</Name>
+ <DisplayName>A sub component, moved to top level</DisplayName>
+ <Description>Install this example.</Description>
+ <Version>0.1.0-1</Version>
+ <ReleaseDate>2010-09-21</ReleaseDate>
+ <SortingPriority>0</SortingPriority>
+ <UpdateFile UncompressedSize="61" CompressedSize="61"/>
+ <TreeName>moved_with_treename</TreeName>
+ </PackageUpdate>
</Updates>
diff --git a/tests/auto/installer/componentmodel/tst_componentmodel.cpp b/tests/auto/installer/componentmodel/tst_componentmodel.cpp
index d5cae916c..276292233 100644
--- a/tests/auto/installer/componentmodel/tst_componentmodel.cpp
+++ b/tests/auto/installer/componentmodel/tst_componentmodel.cpp
@@ -1,3 +1,31 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
#include "component.h"
#include "componentmodel.h"
#include "updatesinfo_p.h"
@@ -9,8 +37,8 @@
using namespace KDUpdater;
using namespace QInstaller;
-#define EXPECTED_COUNT_VIRTUALS_VISIBLE 11
-#define EXPECTED_COUNT_VIRTUALS_INVISIBLE 10
+#define EXPECTED_COUNT_VIRTUALS_VISIBLE 12
+#define EXPECTED_COUNT_VIRTUALS_INVISIBLE 11
static const char vendorProduct[] = "com.vendor.product";
static const char vendorSecondProduct[] = "com.vendor.second.product";
@@ -23,6 +51,7 @@ static const char vendorThirdProductVirtual[] = "com.vendor.third.product.virtua
static const char vendorFourthProductCheckable[] = "com.vendor.fourth.product.checkable";
static const char vendorFifthProductNonCheckable[] = "com.vendor.fifth.product.noncheckable";
static const char vendorFifthProductSub[] = "com.vendor.fifth.product.noncheckable.sub";
+static const char vendorFifthProductSubWithTreeName[] = "moved_with_treename";
static const QMap<QString, QString> rootComponentDisplayNames = {
{"", QLatin1String("The root component")},
@@ -30,6 +59,12 @@ static const QMap<QString, QString> rootComponentDisplayNames = {
{"de_de", QString::fromUtf8("Wurzel Komponente")}
};
+static const QMap<QString, QString> rootComponentDescriptions = {
+ {"", QLatin1String("Install this example.")},
+ {"ru_ru", QString::fromUtf8("Установите этот пример.")},
+ {"de_de", QString::fromUtf8("Installieren Sie dieses Beispiel.")}
+};
+
class tst_ComponentModel : public QObject
{
Q_OBJECT
@@ -38,7 +73,8 @@ public:
enum Option {
NoFlags = 0x00,
VirtualsVisible = 0x01,
- NoForcedInstallation = 0x02
+ NoForcedInstallation = 0x02,
+ NoDefaultInstallation = 0x04
};
Q_DECLARE_FLAGS(Options, Option);
@@ -49,7 +85,7 @@ private slots:
m_defaultPartially << vendorSecondProduct;
m_defaultUnchecked << vendorSecondProductSub1 << vendorSecondProductSubnode
<< vendorSecondProductSubnodeSub << vendorFourthProductCheckable
- << vendorFifthProductSub;
+ << vendorFifthProductSub << vendorFifthProductSubWithTreeName;
m_uncheckable << vendorFifthProductNonCheckable;
}
@@ -62,7 +98,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
// all names should be resolvable, virtual components are not indexed if they are not visible
QStringList all;
@@ -70,7 +106,7 @@ private slots:
foreach (const QString &name, all) {
QVERIFY(model.indexFromComponentName(name).isValid());
QVERIFY(model.componentFromIndex(model.indexFromComponentName(name)) != 0);
- QCOMPARE(model.componentFromIndex(model.indexFromComponentName(name))->name(), name);
+ QCOMPARE(model.componentFromIndex(model.indexFromComponentName(name))->treeName(), name);
}
foreach (Component *const component, rootComponents)
@@ -86,7 +122,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
// all names should be resolvable, including virtual components
QStringList all;
@@ -95,7 +131,7 @@ private slots:
foreach (const QString &name, all) {
QVERIFY(model.indexFromComponentName(name).isValid());
QVERIFY(model.componentFromIndex(model.indexFromComponentName(name)) != 0);
- QCOMPARE(model.componentFromIndex(model.indexFromComponentName(name))->name(), name);
+ QCOMPARE(model.componentFromIndex(model.indexFromComponentName(name))->treeName(), name);
}
foreach (Component *const component, rootComponents)
@@ -111,7 +147,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
testDefaultInheritedModelBehavior(&model, 1);
QCOMPARE(model.core(), &m_core);
@@ -132,7 +168,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
testDefaultInheritedModelBehavior(&model, 1);
QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked);
@@ -154,7 +190,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
testDefaultInheritedModelBehavior(&model, 1);
QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked);
@@ -174,7 +210,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
testDefaultInheritedModelBehavior(&model, 1);
QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked);
@@ -196,7 +232,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
testDefaultInheritedModelBehavior(&model, 1);
// select all possible components.
@@ -232,7 +268,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
testDefaultInheritedModelBehavior(&model, 1);
// select all possible components.
@@ -270,7 +306,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
testDefaultInheritedModelBehavior(&model, 1);
// select all possible components.
@@ -305,7 +341,7 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
testDefaultInheritedModelBehavior(&model, 1);
// select all possible components.
@@ -337,11 +373,19 @@ private slots:
{
QStringList localesToTest = { "en_US", "ru_RU", "de_DE", "fr_FR" };
foreach (const QString &localeToTest, localesToTest) {
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ QLocale::setDefault(QLocale(localeToTest));
+#else
QLocale::setDefault(localeToTest);
+#endif
QString expectedName = rootComponentDisplayNames.contains(localeToTest.toLower())
? rootComponentDisplayNames[localeToTest.toLower()]
: rootComponentDisplayNames[QString()];
+ QString expectedDescription = rootComponentDescriptions.contains(localeToTest.toLower())
+ ? rootComponentDescriptions[localeToTest.toLower()]
+ : rootComponentDescriptions[QString()];
+
setPackageManagerOptions(NoFlags);
QList<Component*> rootComponents = loadComponents();
@@ -349,26 +393,48 @@ private slots:
// setup the model with 1 column
ComponentModel model(1, &m_core);
- model.setRootComponents(rootComponents);
+ model.reset(rootComponents);
const QModelIndex root = model.indexFromComponentName(vendorProduct);
QCOMPARE(model.data(root, Qt::DisplayRole).toString(), expectedName);
+ Component *comp = model.componentFromIndex(root);
+ QCOMPARE(comp->value("Description"), expectedDescription);
+
qDeleteAll(rootComponents);
}
}
+ void testNoDefaultInstallation()
+ {
+ setPackageManagerOptions(NoDefaultInstallation);
+
+ QList<Component*> rootComponents = loadComponents();
+ testComponentsLoaded(rootComponents);
+
+ // setup the model with 1 column
+ ComponentModel model(1, &m_core);
+ model.reset(rootComponents);
+ testDefaultInheritedModelBehavior(&model, 1);
+
+ model.setCheckedState(ComponentModel::DefaultChecked);
+ QCOMPARE(model.checkedState(), ComponentModel::DefaultChecked);
+ testModelState(&model, QStringList() << vendorProduct, QStringList(), m_defaultUnchecked
+ + m_uncheckable + m_defaultPartially + QStringList() << vendorSecondProductSub);
+ }
+
private:
void setPackageManagerOptions(Options flags) const
{
m_core.setNoForceInstallation(flags.testFlag(NoForcedInstallation));
m_core.setVirtualComponentsVisible(flags.testFlag(VirtualsVisible));
+ m_core.setNoDefaultInstallation(flags.testFlag(NoDefaultInstallation));
}
void testComponentsLoaded(const QList<Component *> &rootComponents) const
{
- // we need to have five root components
- QCOMPARE(rootComponents.count(), 5);
+ // we need to have six root components
+ QCOMPARE(rootComponents.count(), 6);
QList<Component*> components = rootComponents;
foreach (Component *const component, rootComponents)
@@ -383,9 +449,9 @@ private:
{
// row count with invalid model index should return:
if (m_core.virtualComponentsVisible())
- QCOMPARE(model->rowCount(), 5); // 5 (4 non virtual and 1 virtual root component)
+ QCOMPARE(model->rowCount(), 6); // 6 (5 non virtual and 1 virtual root component)
else
- QCOMPARE(model->rowCount(), 4); // 4 (the 4 non virtual root components)
+ QCOMPARE(model->rowCount(), 5); // 5 (the 5 non virtual root components)
QCOMPARE(model->columnCount(), columnCount);
const QModelIndex firstParent = model->indexFromComponentName(vendorProduct);
@@ -449,21 +515,22 @@ private:
// these components should have checked state
foreach (Component *const component, model->checked())
- QVERIFY(checked.contains(component->name()));
+ QVERIFY(checked.contains(component->treeName()));
// these components should not have partially checked state
foreach (Component *const component, model->partially())
- QVERIFY(partially.contains(component->name()));
+ QVERIFY(partially.contains(component->treeName()));
// these components should not have checked state
foreach (Component *const component, model->unchecked())
- QVERIFY(unchecked.contains(component->name()));
+ QVERIFY(unchecked.contains(component->treeName()));
}
QList<Component*> loadComponents() const
{
UpdatesInfo updatesInfo;
updatesInfo.setFileName(":///data/updates.xml");
+ updatesInfo.parseFile();
const QList<UpdateInfo> updateInfos = updatesInfo.updatesInfo();
QHash<QString, Component*> components;
@@ -472,10 +539,15 @@ private:
// we need at least these to be able to test the model
component->setValue("Name", info.data.value("Name").toString());
- component->setValue("Default", info.data.value("Default").toString());
+ component->setValue("TreeName", info.data.value("TreeName").value<QPair<QString, bool>>().first);
+ QString isDefault = info.data.value("Default").toString();
+ if (m_core.noDefaultInstallation())
+ isDefault = scFalse;
+ component->setValue("Default", isDefault);
component->setValue("Virtual", info.data.value("Virtual").toString());
component->setValue("DisplayName", info.data.value("DisplayName").toString());
component->setValue("Checkable", info.data.value("Checkable").toString());
+ component->setValue("Description", info.data.value("Description").toString());
QString forced = info.data.value("ForcedInstallation", scFalse).toString().toLower();
if (m_core.noForceInstallation())
@@ -486,7 +558,7 @@ private:
component->setCheckable(false);
component->setCheckState(Qt::Checked);
}
- components.insert(component->name(), component);
+ components.insert(component->treeName(), component);
}
QList <Component*> rootComponents;
@@ -516,6 +588,7 @@ private:
QStringList m_defaultPartially;
QStringList m_defaultUnchecked;
QStringList m_uncheckable;
+ QStringList m_defaultNoChecked;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(tst_ComponentModel::Options)
diff --git a/tests/auto/installer/componentreplace/componentreplace.pro b/tests/auto/installer/componentreplace/componentreplace.pro
new file mode 100644
index 000000000..9df6f81ca
--- /dev/null
+++ b/tests/auto/installer/componentreplace/componentreplace.pro
@@ -0,0 +1,9 @@
+include(../../qttest.pri)
+
+QT += qml
+
+SOURCES += tst_componentreplace.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/componentreplace/data/installPackagesRepository/A.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/installPackagesRepository/A.sub1/1.0.0content.7z
new file mode 100644
index 000000000..adcc21ad7
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/installPackagesRepository/A.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/installPackagesRepository/A/1.0.0content.7z b/tests/auto/installer/componentreplace/data/installPackagesRepository/A/1.0.0content.7z
new file mode 100644
index 000000000..916fdd1d0
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/installPackagesRepository/A/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/installPackagesRepository/B.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/installPackagesRepository/B.sub1/1.0.0content.7z
new file mode 100644
index 000000000..ab63152f8
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/installPackagesRepository/B.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/installPackagesRepository/B/1.0.0content.7z b/tests/auto/installer/componentreplace/data/installPackagesRepository/B/1.0.0content.7z
new file mode 100644
index 000000000..7b957b077
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/installPackagesRepository/B/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/installPackagesRepository/C/1.0.0content.7z b/tests/auto/installer/componentreplace/data/installPackagesRepository/C/1.0.0content.7z
new file mode 100644
index 000000000..d498f1900
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/installPackagesRepository/C/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/installPackagesRepository/Updates.xml b/tests/auto/installer/componentreplace/data/installPackagesRepository/Updates.xml
new file mode 100644
index 000000000..e77207777
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/installPackagesRepository/Updates.xml
@@ -0,0 +1,55 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="74" CompressedSize="224" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>53892cfe4d5f5b978553d3aa172944117604ef9c</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>A.sub1</Name>
+ <DisplayName>A subcomponent 1</DisplayName>
+ <Description>Subcomponent of component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>8bd5a1d2525cfdfb690a3c80165aeed44a17795f</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="74" CompressedSize="224" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>b2d03273f01f45878c3f5081cc8502edc0826e08</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B.sub1</Name>
+ <DisplayName>B subcomponent 1</DisplayName>
+ <Description>Subcomponent of component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>a10463141e30ce3fede9ac84bc52a07b0c5e919e</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C component</DisplayName>
+ <Description>Component C</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>a10463141e30ce3fede9ac84bc52a07b0c5e919e</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/A.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/A.sub1/1.0.0content.7z
new file mode 100644
index 000000000..adcc21ad7
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/A.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/A/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/A/1.0.0content.7z
new file mode 100644
index 000000000..916fdd1d0
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/A/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/B.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/B.sub1/1.0.0content.7z
new file mode 100644
index 000000000..ab63152f8
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/B.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/B/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/B/1.0.0content.7z
new file mode 100644
index 000000000..7b957b077
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/B/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/Updates.xml b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/Updates.xml
new file mode 100644
index 000000000..c6b85077b
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplace/Updates.xml
@@ -0,0 +1,46 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="74" CompressedSize="224" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>dd48e40f2f86559b20288424a6a3e2a1a05a172d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>A.sub1</Name>
+ <DisplayName>A subcomponent 1</DisplayName>
+ <Description>Subcomponent of component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>f8ff5da138516b1f800e641ab4999301dcb3c78b</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Replaces>A, A.sub1</Replaces>
+ <UpdateFile UncompressedSize="74" CompressedSize="224" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>8e83334a4a3c9c9d2bb6b073858d980da2c8871f</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B.sub1</Name>
+ <DisplayName>B subcomponent 1</DisplayName>
+ <Description>Subcomponent of component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>36d374bbbfbe87a18f6b308e5398360e9cc54a84</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/A.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/A.sub1/1.0.0content.7z
new file mode 100644
index 000000000..adcc21ad7
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/A.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/A/2.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/A/2.0.0content.7z
new file mode 100644
index 000000000..916fdd1d0
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/A/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/B.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/B.sub1/1.0.0content.7z
new file mode 100644
index 000000000..ab63152f8
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/B.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/B/2.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/B/2.0.0content.7z
new file mode 100644
index 000000000..7b957b077
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/B/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7z
new file mode 100644
index 000000000..d498f1900
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/Updates.xml b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/Updates.xml
new file mode 100644
index 000000000..e0fb351ff
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithMultiReplaceInUpdate/Updates.xml
@@ -0,0 +1,56 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="74" OS="Any" CompressedSize="224"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>28cd1210a590a97a9c0507cc39519b55d8f0a08b</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>A.sub1</Name>
+ <DisplayName>A subcomponent 1</DisplayName>
+ <Description>Subcomponent of component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" OS="Any" CompressedSize="247"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>9295f5a7f58c5e27a1c9ecf580f54a9328085aa5</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Replaces>A, A.sub1</Replaces>
+ <UpdateFile UncompressedSize="74" OS="Any" CompressedSize="224"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>b55f66866b7b909021f517941e921fd183fac7b0</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B.sub1</Name>
+ <DisplayName>B subcomponent 1</DisplayName>
+ <Description>Subcomponent of component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" OS="Any" CompressedSize="247"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>4331736562fc047a4f47263be75f816298cbda30</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C component</DisplayName>
+ <Description>Component C</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>a10463141e30ce3fede9ac84bc52a07b0c5e919e</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithReplace/A.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithReplace/A.sub1/1.0.0content.7z
new file mode 100644
index 000000000..adcc21ad7
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithReplace/A.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithReplace/A/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithReplace/A/1.0.0content.7z
new file mode 100644
index 000000000..916fdd1d0
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithReplace/A/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithReplace/B.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithReplace/B.sub1/1.0.0content.7z
new file mode 100644
index 000000000..ab63152f8
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithReplace/B.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithReplace/B/2.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithReplace/B/2.0.0content.7z
new file mode 100644
index 000000000..7b957b077
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithReplace/B/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithReplace/Updates.xml b/tests/auto/installer/componentreplace/data/repositoryWithReplace/Updates.xml
new file mode 100644
index 000000000..ec74ac3e5
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithReplace/Updates.xml
@@ -0,0 +1,46 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="74" CompressedSize="224" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>dba535b00f3ee2bc8387a299940384af3af3489b</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>A.sub1</Name>
+ <DisplayName>A subcomponent 1</DisplayName>
+ <Description>Subcomponent of component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>ca3e5cdf08361775f744a6d6ec1837aae03cdc28</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Replaces>A</Replaces>
+ <UpdateFile UncompressedSize="74" CompressedSize="224" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c30d2146844195d27879e5360e864c4eae7b4cde</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B.sub1</Name>
+ <DisplayName>B subcomponent 1</DisplayName>
+ <Description>Subcomponent of component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile UncompressedSize="89" CompressedSize="247" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>05124ea8feadb6a5d8d9222cc41898ef72d562bb</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/A.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/A.sub1/1.0.0content.7z
new file mode 100644
index 000000000..adcc21ad7
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/A.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/A/2.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/A/2.0.0content.7z
new file mode 100644
index 000000000..916fdd1d0
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/A/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/B.sub1/1.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/B.sub1/1.0.0content.7z
new file mode 100644
index 000000000..ab63152f8
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/B.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/B/2.0.0content.7z b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/B/2.0.0content.7z
new file mode 100644
index 000000000..7b957b077
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/B/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/Updates.xml b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/Updates.xml
new file mode 100644
index 000000000..b1846f7b1
--- /dev/null
+++ b/tests/auto/installer/componentreplace/data/repositoryWithUpdateToReplaceble/Updates.xml
@@ -0,0 +1,46 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>a0dc47264727fd2e6a6cdd2fa879388eb732ac73</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>A.sub1</Name>
+ <DisplayName>A subcomponent 1</DisplayName>
+ <Description>Subcomponent of component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile CompressedSize="247" OS="Any" UncompressedSize="89"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>7b5fb2c36cb4a784816c34839d7ce4ac0114df50</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Replaces>A</Replaces>
+ <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>9baaa7eaca7002ba10addc22306bb9383d2e5b46</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B.sub1</Name>
+ <DisplayName>B subcomponent 1</DisplayName>
+ <Description>Subcomponent of component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <UpdateFile CompressedSize="247" OS="Any" UncompressedSize="89"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>f840d6cd369d9dc471f0a718ff5c8c000d07d72c</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/componentreplace/settings.qrc b/tests/auto/installer/componentreplace/settings.qrc
new file mode 100644
index 000000000..ba1b0ab98
--- /dev/null
+++ b/tests/auto/installer/componentreplace/settings.qrc
@@ -0,0 +1,31 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/installPackagesRepository/Updates.xml</file>
+ <file>data/installPackagesRepository/A/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/B/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/A.sub1/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/B.sub1/1.0.0content.7z</file>
+ <file>data/installPackagesRepository/C/1.0.0content.7z</file>
+ <file>data/repositoryWithReplace/Updates.xml</file>
+ <file>data/repositoryWithReplace/A/1.0.0content.7z</file>
+ <file>data/repositoryWithReplace/B/2.0.0content.7z</file>
+ <file>data/repositoryWithReplace/A.sub1/1.0.0content.7z</file>
+ <file>data/repositoryWithReplace/B.sub1/1.0.0content.7z</file>
+ <file>data/repositoryWithUpdateToReplaceble/Updates.xml</file>
+ <file>data/repositoryWithUpdateToReplaceble/A/2.0.0content.7z</file>
+ <file>data/repositoryWithUpdateToReplaceble/B/2.0.0content.7z</file>
+ <file>data/repositoryWithUpdateToReplaceble/A.sub1/1.0.0content.7z</file>
+ <file>data/repositoryWithUpdateToReplaceble/B.sub1/1.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplace/Updates.xml</file>
+ <file>data/repositoryWithMultiReplace/A/1.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplace/B/1.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplace/A.sub1/1.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplace/B.sub1/1.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplaceInUpdate/Updates.xml</file>
+ <file>data/repositoryWithMultiReplaceInUpdate/A/2.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplaceInUpdate/B/2.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplaceInUpdate/A.sub1/1.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplaceInUpdate/B.sub1/1.0.0content.7z</file>
+ <file>data/repositoryWithMultiReplaceInUpdate/C/2.0.0content.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/componentreplace/tst_componentreplace.cpp b/tests/auto/installer/componentreplace/tst_componentreplace.cpp
new file mode 100644
index 000000000..98fee27d0
--- /dev/null
+++ b/tests/auto/installer/componentreplace/tst_componentreplace.cpp
@@ -0,0 +1,286 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <component.h>
+#include <packagemanagercore.h>
+
+#include <QLoggingCategory>
+#include <QTest>
+
+using namespace QInstaller;
+
+class tst_ComponentReplace : public QObject
+{
+ Q_OBJECT
+
+private:
+ void setRepository(const QString &repository, PackageManagerCore *core)
+ {
+ core->cancelMetaInfoJob(); //Call cancel to reset metadata so that update repositories are fetched
+
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(repository);
+ repoList.insert(repo);
+ core->settings().setDefaultRepositories(repoList);
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_installDir = QInstaller::generateTemporaryFileName();
+ }
+
+ void replaceNonInstalledItem()
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repositoryWithReplace"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A" << "B"));
+ QList<Component*> installedComponents = core->orderedComponentsToInstall();
+
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "2.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Bsub1.txt" << "B.txt");
+ }
+
+ void replaceInstalledItem()
+ {
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A"));
+
+ QCOMPARE(core->orderedComponentsToInstall().count(), 2);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt");
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ setRepository(":///data/repositoryWithReplace", core);
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "B"));
+ QCOMPARE(core->componentsToUninstall().count(), 1);
+ QVERIFY(core->componentByName("B.sub1") != 0);
+ QVERIFY(core->componentByName("B") != 0);
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "2.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Bsub1.txt" << "B.txt" << "Asub1.txt");
+ delete core;
+ }
+
+ void replaceInstalledItemInUpdate()
+ {
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A" << "B"));
+
+ QCOMPARE(core->orderedComponentsToInstall().count(), 4);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt");
+
+ core->commitSessionOperations();
+ core->setUpdater();
+ setRepository(":///data/repositoryWithReplace", core);
+ QCOMPARE(PackageManagerCore::Success, core->updateComponentsSilently(QStringList() << "B"));
+ QCOMPARE(core->componentsToUninstall().count(), 1);
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "2.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Bsub1.txt" << "B.txt" << "Asub1.txt");
+ delete core;
+ }
+
+ void replaceInstalledItemContainingUpdateInUpdate()
+ {
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A" << "B"));
+
+ QCOMPARE(core->orderedComponentsToInstall().count(), 4);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt");
+
+ core->commitSessionOperations();
+ core->setUpdater();
+ setRepository(":///data/repositoryWithUpdateToReplaceble", core);
+ QCOMPARE(PackageManagerCore::Success, core->updateComponentsSilently(QStringList() << "B"));
+ QCOMPARE(core->componentsToUninstall().count(), 1);
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "2.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "2.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Bsub1.txt" << "B.txt" << "Asub1.txt");
+ delete core;
+ }
+
+ void replaceMultipleInstalledItems()
+ {
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A"));
+
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt");
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ setRepository(":///data/repositoryWithMultiReplace", core);
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "B"));
+ QCOMPARE(core->componentsToUninstall().count(), 2);
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Bsub1.txt" << "B.txt");
+ delete core;
+ }
+
+ void replaceMultipleInstalledItemsInUpdate()
+ {
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A" << "B"));
+
+ QCOMPARE(core->orderedComponentsToInstall().count(), 4);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt");
+
+ core->commitSessionOperations();
+ core->setUpdater();
+ setRepository(":///data/repositoryWithMultiReplaceInUpdate", core);
+ QCOMPARE(PackageManagerCore::Success, core->updateComponentsSilently(QStringList() << "B"));
+ QCOMPARE(core->componentsToUninstall().count(), 2);
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResourceFileDeletion(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "2.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Bsub1.txt" << "B.txt");
+ delete core;
+ }
+
+ void installOtherComponentsWhileReplacementsExists()
+ {
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A" << "B"));
+
+ QCOMPARE(core->orderedComponentsToInstall().count(), 4);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt");
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ setRepository(":///data/repositoryWithMultiReplaceInUpdate", core);
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "C"));
+ QCOMPARE(core->orderedComponentsToInstall().count(), 1);
+ QCOMPARE(core->componentsToUninstall().count(), 0);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "C", "2.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt" << "C.txt");
+
+ delete core;
+ }
+
+ void updateOtherComponentsWhileReplacementsExists()
+ {
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/installPackagesRepository");
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "A" << "B" << "C"));
+
+ QCOMPARE(core->orderedComponentsToInstall().count(), 5);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt" << "C.txt");
+
+ core->commitSessionOperations();
+ core->setUpdater();
+ setRepository(":///data/repositoryWithMultiReplaceInUpdate", core);
+ QCOMPARE(PackageManagerCore::Success, core->updateComponentsSilently(QStringList() << "C"));
+ QCOMPARE(core->orderedComponentsToInstall().count(), 1);
+ QCOMPARE(core->componentsToUninstall().count(), 0);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "A.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "B.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "C", "2.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "Asub1.txt" << "A.txt"<< "Bsub1.txt" << "B.txt" << "C.txt");
+
+ delete core;
+ }
+
+ void cleanup()
+ {
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+private:
+ QString m_installDir;
+};
+
+
+QTEST_MAIN(tst_ComponentReplace)
+
+#include "tst_componentreplace.moc"
diff --git a/tests/auto/installer/consumeoutputoperationtest/consumeoutputoperationtest.pro b/tests/auto/installer/consumeoutputoperationtest/consumeoutputoperationtest.pro
index 3eacd46ac..30a85bdcf 100644
--- a/tests/auto/installer/consumeoutputoperationtest/consumeoutputoperationtest.pro
+++ b/tests/auto/installer/consumeoutputoperationtest/consumeoutputoperationtest.pro
@@ -6,3 +6,7 @@ QT += testlib qml
SOURCES = tst_consumeoutputoperationtest.cpp
DEFINES += "QMAKE_BINARY=$$fromNativeSeparators($$QMAKE_BINARY)"
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/consumeoutputoperationtest/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/consumeoutputoperationtest/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..5415d3b9f
--- /dev/null
+++ b/tests/auto/installer/consumeoutputoperationtest/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/consumeoutputoperationtest/data/repository/Updates.xml b/tests/auto/installer/consumeoutputoperationtest/data/repository/Updates.xml
new file mode 100644
index 000000000..1c3caf7be
--- /dev/null
+++ b/tests/auto/installer/consumeoutputoperationtest/data/repository/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>4da14562d6515590d145678d21990faa817832bb</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/consumeoutputoperationtest/settings.qrc b/tests/auto/installer/consumeoutputoperationtest/settings.qrc
new file mode 100644
index 000000000..d030220ab
--- /dev/null
+++ b/tests/auto/installer/consumeoutputoperationtest/settings.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/consumeoutputoperationtest/tst_consumeoutputoperationtest.cpp b/tests/auto/installer/consumeoutputoperationtest/tst_consumeoutputoperationtest.cpp
index 8250a7dd2..c0c8d7390 100644
--- a/tests/auto/installer/consumeoutputoperationtest/tst_consumeoutputoperationtest.cpp
+++ b/tests/auto/installer/consumeoutputoperationtest/tst_consumeoutputoperationtest.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -25,19 +25,15 @@
** $QT_END_LICENSE$
**
**************************************************************************/
-#include <init.h>
+#include "../shared/packagemanager.h"
+
#include <packagemanagercore.h>
#include <consumeoutputoperation.h>
#include <qinstallerglobal.h>
-#include <fileutils.h>
#include <errors.h>
-#include <QObject>
#include <QTest>
#include <QProcess>
-#include <QDir>
-#include <QEventLoop>
-#include <QDebug>
#define QUOTE_(x) #x
#define QUOTE(x) QUOTE_(x)
@@ -58,6 +54,8 @@ private slots:
m_fakeQtPath = QDir::toNativeSeparators(qApp->applicationDirPath()) + QDir::separator()
+ "fakeQt" + QDir::separator();
QVERIFY(QDir().mkpath(m_fakeQtPath + "bin"));
+ m_testOutput = getOutputFrom(QUOTE(QMAKE_BINARY), QStringList("-query"));
+ qputenv("qmakePath", QUOTE(QMAKE_BINARY)); //Read from script
}
void testMissingArguments()
@@ -81,15 +79,28 @@ private slots:
void testGetOutputFromQmake()
{
- QString testOutput = getOutputFrom(QUOTE(QMAKE_BINARY), QStringList("-query"));
-
ConsumeOutputOperation operation(&m_core);
operation.setArguments(QStringList() << "testConsumeOutputKey" << QUOTE(QMAKE_BINARY) << "-query");
QVERIFY2(operation.performOperation(), qPrintable(operation.errorString()));
QCOMPARE(Operation::Error(operation.error()), Operation::NoError);
- QCOMPARE(m_core.value("testConsumeOutputKey"), testOutput);
+ QCOMPARE(m_core.value("testConsumeOutputKey"), m_testOutput);
+ }
+
+ void testPerformingFromCLI()
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, ":///data/repository");
+
+ core->installDefaultComponentsSilently();
+ QCOMPARE(core->value("testConsumeOutputKeyFromScript"), m_testOutput);
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
}
void cleanupTestCase()
@@ -99,6 +110,7 @@ private slots:
} catch (const QInstaller::Error &error) {
QFAIL(qPrintable(error.message()));
}
+ qunsetenv("qmakePath");
}
private:
@@ -113,12 +125,13 @@ private:
if (process.state() != QProcess::NotRunning)
loop.exec();
- return process.readAllStandardOutput();
+ return process.readAllStandardOutput().trimmed();
}
PackageManagerCore m_core;
QString m_fakeQtPath;
+ QString m_testOutput;
};
QTEST_MAIN(tst_consumeoutputoperationtest)
diff --git a/tests/auto/installer/contentsha1check/contentsha1check.pro b/tests/auto/installer/contentsha1check/contentsha1check.pro
new file mode 100644
index 000000000..dd659bffa
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/contentsha1check.pro
@@ -0,0 +1,9 @@
+include(../../qttest.pri)
+
+QT += qml
+
+SOURCES += tst_contentsha1check.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/contentsha1check/data/config.xml b/tests/auto/installer/contentsha1check/data/config.xml
new file mode 100644
index 000000000..041ce5062
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/config.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Installer>
+ <Name>Your application</Name>
+ <Version>1.2.3</Version>
+ <MaintenanceToolName></MaintenanceToolName>
+ <MaintenanceToolIniFile></MaintenanceToolIniFile>
+ <TargetConfigurationFile></TargetConfigurationFile>
+</Installer>
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z
new file mode 100644
index 000000000..9109d284f
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha1 b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha1
new file mode 100644
index 000000000..564e8290b
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha1
@@ -0,0 +1 @@
+eb5a464ab1a33bd1484e9b8f22b2c5f97abdfdf6 \ No newline at end of file
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z
new file mode 100644
index 000000000..947979354
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha1 b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..0f2144f0c
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+7e592e4b96adcefc77f2613100a3bd5e8835cce0 \ No newline at end of file
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1meta.7z
new file mode 100644
index 000000000..c14f55e4a
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/B/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/Updates.xml b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/Updates.xml
new file mode 100644
index 000000000..1d2fb780b
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithchecksumcheck/Updates.xml
@@ -0,0 +1,27 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile UncompressedSize="74" CompressedSize="215" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>dec2797a059da9303fec87cc0c1dfb0866afeb8f</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile UncompressedSize="74" CompressedSize="215" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>2370e0b7dae861088c056d2de40c7ab7051bda13</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z
new file mode 100644
index 000000000..793ce161c
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha1 b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha1
new file mode 100644
index 000000000..641396e0f
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha1
@@ -0,0 +1 @@
+2c185d45cb84cec7a71e317f8cfc64dd23094c32 \ No newline at end of file
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1meta.7z
new file mode 100644
index 000000000..4feab5c34
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/E/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z
new file mode 100644
index 000000000..f53a705dd
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha1 b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..daf89acba
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+d33a5fb638047372e9793b48d6c5ff85da560595 \ No newline at end of file
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1meta.7z
new file mode 100644
index 000000000..9931c0a7f
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/F/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/Updates.xml b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/Updates.xml
new file mode 100644
index 000000000..bda013684
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithinvalidchecksum/Updates.xml
@@ -0,0 +1,27 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>E</Name>
+ <DisplayName>E</DisplayName>
+ <Description>Example component E, invalid checksum</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="215" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>db7e010425aaaaaaeebc6281a9d4c91e5666fd8f</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>F</Name>
+ <DisplayName>F</DisplayName>
+ <Description>Example component F</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="215" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>b69b864cef5d0aecb496273374dd24bb8cba83bd</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1content.7z
new file mode 100644
index 000000000..f96bfa9a3
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1meta.7z
new file mode 100644
index 000000000..976c57b43
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/C/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1content.7z b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1content.7z
new file mode 100644
index 000000000..015670af0
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1meta.7z b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1meta.7z
new file mode 100644
index 000000000..0b36609d7
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/D/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/Updates.xml b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/Updates.xml
new file mode 100644
index 000000000..ae2ba911a
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/data/repositorywithnochecksumcheck/Updates.xml
@@ -0,0 +1,27 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile OS="Any" UncompressedSize="74" CompressedSize="215"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>f82e1d1bbfd252715ace26db8c62595252e28a3b</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>D</Name>
+ <DisplayName>D</DisplayName>
+ <Description>Example component D</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile OS="Any" UncompressedSize="74" CompressedSize="215"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>402f299ec90f215db390b150c9429101344cf1ea</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/contentsha1check/settings.qrc b/tests/auto/installer/contentsha1check/settings.qrc
new file mode 100644
index 000000000..e150ea61e
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/settings.qrc
@@ -0,0 +1,18 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/config.xml</file>
+ <file>data/repositorywithchecksumcheck/Updates.xml</file>
+ <file>data/repositorywithchecksumcheck/A/1.0.2-1content.7z</file>
+ <file>data/repositorywithchecksumcheck/A/1.0.2-1content.7z.sha1</file>
+ <file>data/repositorywithchecksumcheck/B/1.0.0-1content.7z</file>
+ <file>data/repositorywithchecksumcheck/B/1.0.0-1content.7z.sha1</file>
+ <file>data/repositorywithnochecksumcheck/Updates.xml</file>
+ <file>data/repositorywithnochecksumcheck/C/1.0.2-1content.7z</file>
+ <file>data/repositorywithnochecksumcheck/D/1.0.0-1content.7z</file>
+ <file>data/repositorywithinvalidchecksum/Updates.xml</file>
+ <file>data/repositorywithinvalidchecksum/E/1.0.2-1content.7z</file>
+ <file>data/repositorywithinvalidchecksum/E/1.0.2-1content.7z.sha1</file>
+ <file>data/repositorywithinvalidchecksum/F/1.0.0-1content.7z</file>
+ <file>data/repositorywithinvalidchecksum/F/1.0.0-1content.7z.sha1</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/contentsha1check/tst_contentsha1check.cpp b/tests/auto/installer/contentsha1check/tst_contentsha1check.cpp
new file mode 100644
index 000000000..e587d3011
--- /dev/null
+++ b/tests/auto/installer/contentsha1check/tst_contentsha1check.cpp
@@ -0,0 +1,181 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <component.h>
+#include <packagemanagercore.h>
+
+#include <QLoggingCategory>
+#include <QTest>
+#include <QMessageBox>
+
+using namespace QInstaller;
+
+typedef QList<QPair<QString, QString> > ComponentResourceHash;
+typedef QPair<QString, QString> ComponentResource;
+
+static QStringList expectedMessages;
+
+void downloadingArchiveOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ Q_UNUSED(type)
+ Q_UNUSED(context)
+ QByteArray localMsg = msg.toLocal8Bit();
+ if (!msg.startsWith("Downloading archive"))
+ return;
+ if (expectedMessages.contains(msg))
+ expectedMessages.removeOne(msg);
+}
+
+class tst_ContentSha1Check : public QObject
+{
+ Q_OBJECT
+
+private slots:
+
+ void testInstall_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QStringList>("installComponents");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+ QTest::addColumn<ComponentResourceHash>("componentResources");
+ QTest::addColumn<QStringList >("installedFiles");
+ QTest::addColumn<QStringList >("expectedDownloadingArchiveMessages");
+
+ /*********** Install with checksum check **********/
+ ComponentResourceHash componentResources;
+ componentResources.append(ComponentResource("A", "1.0.2-1content.txt"));
+ componentResources.append(ComponentResource("B", "1.0.0-1content.txt"));
+
+ QTest::newRow("Check checksum")
+ << ":///data/repositorywithchecksumcheck"
+ << (QStringList() << "A" << "B")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "A.txt" << "B.txt")
+ << (QStringList() << "Downloading archive \"1.0.2-1content.7z.sha1\" for component A."
+ << "Downloading archive \"1.0.2-1content.7z\" for component A."
+ << "Downloading archive \"1.0.0-1content.7z.sha1\" for component B."
+ << "Downloading archive \"1.0.0-1content.7z\" for component B.");
+
+ /*********** Install with and without checksum check **********/
+ componentResources.clear();
+ componentResources.append(ComponentResource("C", "1.0.2-1content.txt"));
+ componentResources.append(ComponentResource("D", "1.0.0-1content.txt"));
+
+ QTest::newRow("Without checksum check")
+ << ":///data/repositorywithnochecksumcheck"
+ << (QStringList() << "C" << "D")
+ << PackageManagerCore::Success
+ << componentResources
+ << (QStringList() << "components.xml" << "C.txt" << "D.txt")
+ << (QStringList() << "Downloading archive \"1.0.2-1content.7z\" for component C."
+ << "Downloading archive \"1.0.0-1content.7z\" for component D.");
+
+ }
+
+ void testInstallWithInvalidChecksum_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QStringList>("installComponents");
+ QTest::addColumn<PackageManagerCore::Status>("status");
+ QTest::addColumn<ComponentResourceHash>("componentResources");
+ QTest::addColumn<QStringList >("installedFiles");
+
+ /*********** Install with checksum check **********/
+ ComponentResourceHash componentResources;
+
+ QTest::newRow("Invalid checksum")
+ << ":///data/repositorywithinvalidchecksum"
+ << (QStringList() << "E" << "F")
+ << PackageManagerCore::Failure
+ << componentResources
+ << (QStringList());
+ }
+
+ void testInstall()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QStringList, installComponents);
+ QFETCH(PackageManagerCore::Status, status);
+ QFETCH(ComponentResourceHash, componentResources);
+ QFETCH(QStringList, installedFiles);
+ QFETCH(QStringList, expectedDownloadingArchiveMessages);
+
+ expectedMessages = expectedDownloadingArchiveMessages;
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, repository));
+ qInstallMessageHandler(downloadingArchiveOutput);
+
+ QCOMPARE(status, core->installSelectedComponentsSilently(QStringList() << installComponents));
+ for (const ComponentResource &resource : componentResources)
+ VerifyInstaller::verifyInstallerResources(m_installDir, resource.first, resource.second);
+ VerifyInstaller::verifyFileExistence(m_installDir, installedFiles);
+
+ QVERIFY(expectedMessages.isEmpty());
+ }
+
+ void testInstallWithInvalidChecksum()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QStringList, installComponents);
+ QFETCH(PackageManagerCore::Status, status);
+ QFETCH(ComponentResourceHash, componentResources);
+ QFETCH(QStringList, installedFiles);
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, repository));
+ core->setMessageBoxAutomaticAnswer("DownloadError", QMessageBox::Cancel);
+ core->setMessageBoxAutomaticAnswer("installationError", QMessageBox::Ok);
+
+ QCOMPARE(status, core->installSelectedComponentsSilently(QStringList() << installComponents));
+ QVERIFY(!QDir().exists(m_installDir));
+ }
+
+ void init()
+ {
+ m_installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_installDir));
+ }
+
+ void cleanup()
+ {
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
+private:
+ QString m_installDir;
+ QStringList m_expectedMessages;
+};
+
+
+QTEST_MAIN(tst_ContentSha1Check)
+
+#include "tst_contentsha1check.moc"
diff --git a/tests/auto/installer/contentshaupdate/contentshaupdate.pro b/tests/auto/installer/contentshaupdate/contentshaupdate.pro
new file mode 100644
index 000000000..dd7b885fc
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/contentshaupdate.pro
@@ -0,0 +1,9 @@
+include(../../qttest.pri)
+
+QT += qml
+
+SOURCES += tst_contentshaupdate.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/contentshaupdate/data/repository/Updates.xml b/tests/auto/installer/contentshaupdate/data/repository/Updates.xml
new file mode 100644
index 000000000..a83d41384
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repository/Updates.xml
@@ -0,0 +1,48 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="283" UncompressedSize="101"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>10</ContentSha1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>90</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="283" UncompressedSize="101"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C</DisplayName>
+ <Description>Component C</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="283" UncompressedSize="101"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>10</ContentSha1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D</DisplayName>
+ <Description>Component D</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>10</ContentSha1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/contentshaupdate/data/repository/componentA/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repository/componentA/1.0.0content.7z
new file mode 100644
index 000000000..46a9f1d1e
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repository/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repository/componentB/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repository/componentB/1.0.0content.7z
new file mode 100644
index 000000000..5f1fb2e1b
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repository/componentB/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repository/componentC/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repository/componentC/1.0.0content.7z
new file mode 100644
index 000000000..83e82b5a3
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repository/componentC/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repository/componentD/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repository/componentD/1.0.0content.7z
new file mode 100644
index 000000000..da50742a4
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repository/componentD/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/Updates.xml b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/Updates.xml
new file mode 100644
index 000000000..87017cf91
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/Updates.xml
@@ -0,0 +1,48 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>Component A.</Description>
+ <Version>0.1.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>5</ContentSha1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>Component B.</Description>
+ <Version>0.1.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>90</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>10</ContentSha1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C</DisplayName>
+ <Description>Component C</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>10</ContentSha1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D</DisplayName>
+ <Description>Component D</Description>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile UncompressedSize="101" CompressedSize="283" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentA/0.1.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentA/0.1.0content.7z
new file mode 100644
index 000000000..bdbabc7fd
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentA/0.1.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentB/0.1.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentB/0.1.0content.7z
new file mode 100644
index 000000000..1c1129b9f
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentB/0.1.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentC/2.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentC/2.0.0content.7z
new file mode 100644
index 000000000..7f75bf503
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentC/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentD/2.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentD/2.0.0content.7z
new file mode 100644
index 000000000..4207dfbf2
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdate/componentD/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml
new file mode 100644
index 000000000..fe5dc4dec
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/Updates.xml
@@ -0,0 +1,28 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>Component A.</Description>
+ <Version>0.1.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>5</ContentSha1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentEssential</Name>
+ <DisplayName>Component Essential</DisplayName>
+ <Description>Component Essential</Description>
+ <Essential>true</Essential>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile UncompressedSize="101" CompressedSize="283" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>10</ContentSha1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z
new file mode 100644
index 000000000..bdbabc7fd
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentA/0.1.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z
new file mode 100644
index 000000000..9c86042c0
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml
new file mode 100644
index 000000000..f76c03faa
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/Updates.xml
@@ -0,0 +1,27 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile OS="Any" CompressedSize="283" UncompressedSize="101"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <ContentSha1>10</ContentSha1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentEssential</Name>
+ <DisplayName>Component Essential</DisplayName>
+ <Description>Component Essential</Description>
+ <Essential>true</Essential>
+ <Version>2.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile UncompressedSize="101" CompressedSize="283" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7z
new file mode 100644
index 000000000..46a9f1d1e
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z
new file mode 100644
index 000000000..435f260ee
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/data/repositoryWithEssential/componentEssential/2.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/contentshaupdate/settings.qrc b/tests/auto/installer/contentshaupdate/settings.qrc
new file mode 100644
index 000000000..e3426be92
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/settings.qrc
@@ -0,0 +1,20 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/componentA/1.0.0content.7z</file>
+ <file>data/repository/componentB/1.0.0content.7z</file>
+ <file>data/repository/componentC/1.0.0content.7z</file>
+ <file>data/repository/componentD/1.0.0content.7z</file>
+ <file>data/repositoryWithEssential/Updates.xml</file>
+ <file>data/repositoryWithEssential/componentA/1.0.0content.7z</file>
+ <file>data/repositoryWithEssential/componentEssential/2.0.0content.7z</file>
+ <file>data/repositoryUpdate/Updates.xml</file>
+ <file>data/repositoryUpdate/componentA/0.1.0content.7z</file>
+ <file>data/repositoryUpdate/componentB/0.1.0content.7z</file>
+ <file>data/repositoryUpdate/componentC/2.0.0content.7z</file>
+ <file>data/repositoryUpdate/componentD/2.0.0content.7z</file>
+ <file>data/repositoryUpdateWithEssential/Updates.xml</file>
+ <file>data/repositoryUpdateWithEssential/componentA/0.1.0content.7z</file>
+ <file>data/repositoryUpdateWithEssential/componentEssential/1.0.0content.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp b/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp
new file mode 100644
index 000000000..5d282fe38
--- /dev/null
+++ b/tests/auto/installer/contentshaupdate/tst_contentshaupdate.cpp
@@ -0,0 +1,124 @@
+/**************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <QTest>
+
+using namespace QInstaller;
+
+class tst_ContentSha1Update : public QObject
+{
+ Q_OBJECT
+
+private:
+ void setRepository(const QString &repository)
+ {
+ core->reset();
+ core->cancelMetaInfoJob(); //Call cancel to reset metadata so that update repositories are fetched
+
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(repository);
+ repoList.insert(repo);
+ core->settings().setDefaultRepositories(repoList);
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_installDir = QInstaller::generateTemporaryFileName();
+ core = PackageManager::getPackageManagerWithInit(m_installDir);
+ }
+
+ void updateWithContentSha1_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QString>("repositoryForUpdate");
+ QTest::addColumn<QString>("component");
+ QTest::addColumn<QString>("content");
+ QTest::addColumn<QString>("updatedContent");
+ QTest::addColumn<PackageManagerCore::Status>("expectedStatusAfterInstall");
+ QTest::addColumn<PackageManagerCore::Status>("expectedStatusAfterUpdate");
+
+ QTest::newRow("Sha1UpdateForEssential")
+ << ":///data/repositoryWithEssential" << ":///data/repositoryUpdateWithEssential"
+ << "componentEssential" << "2.0.0content.txt" << "1.0.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::EssentialUpdated;
+ QTest::newRow("ContentSha1Change")
+ << ":///data/repository" << ":///data/repositoryUpdate" << "componentA" << "1.0.0content.txt" << "0.1.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::Success;
+ QTest::newRow("NewContentSha1")
+ << ":///data/repository" << ":///data/repositoryUpdate" << "componentB" << "1.0.0content.txt" << "0.1.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::Success;
+ QTest::newRow("SameContentSha1")
+ << ":///data/repository" << ":///data/repositoryUpdate" << "componentC" << "1.0.0content.txt" << "1.0.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::Canceled;
+ QTest::newRow("Sha1RemovedFromRepo")
+ << ":///data/repository" << ":///data/repositoryUpdate" << "componentD" << "1.0.0content.txt" << "2.0.0content.txt"
+ << PackageManagerCore::Success << PackageManagerCore::Success;
+ }
+
+ void updateWithContentSha1()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QString, repositoryForUpdate);
+ QFETCH(QString, component);
+ QFETCH(QString, content);
+ QFETCH(QString, updatedContent);
+ QFETCH(PackageManagerCore::Status, expectedStatusAfterInstall);
+ QFETCH(PackageManagerCore::Status, expectedStatusAfterUpdate);
+
+ setRepository(repository);
+ QCOMPARE(expectedStatusAfterInstall, core->installSelectedComponentsSilently(QStringList() << component));
+ QCOMPARE(expectedStatusAfterInstall, core->status());
+ VerifyInstaller::verifyInstallerResources(m_installDir, component, content);
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ setRepository(repositoryForUpdate);
+ QCOMPARE(expectedStatusAfterUpdate, core->updateComponentsSilently(QStringList()));
+ VerifyInstaller::verifyInstallerResources(m_installDir, component, updatedContent);
+ }
+
+ void cleanupTestCase()
+ {
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+ delete core;
+ }
+
+private:
+ QString m_installDir;
+ PackageManagerCore *core;
+};
+
+
+QTEST_MAIN(tst_ContentSha1Update)
+
+#include "tst_contentshaupdate.moc"
diff --git a/tests/auto/installer/copydirectoryoperation/copydirectoryoperation.pro b/tests/auto/installer/copydirectoryoperation/copydirectoryoperation.pro
new file mode 100644
index 000000000..c3d7d17b9
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/copydirectoryoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_copydirectoryoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/copydirectoryoperation/data/repository/A/1.0.2-1content.7z b/tests/auto/installer/copydirectoryoperation/data/repository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..920ed1d99
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/data/repository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/copydirectoryoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/copydirectoryoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..7449d052b
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/copydirectoryoperation/data/repository/Updates.xml b/tests/auto/installer/copydirectoryoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..fb8c9cf1c
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/data/repository/Updates.xml
@@ -0,0 +1,16 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>4fd4dd023111fcbbdd1221032c2984d249f4cad1</SHA1>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/A/1.0.2-1content.7z b/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..920ed1d99
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/A/1.0.2-1meta.7z b/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..7449d052b
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..b495f3307
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,24 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <SHA1>4fd4dd023111fcbbdd1221032c2984d249f4cad1</SHA1>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Operations>
+ <Operation name="Mkdir">
+ <Argument>@TargetDir@/destination/directory</Argument>
+ </Operation>
+ <Operation name="CopyDirectory">
+ <Argument>@TargetDir@/directory</Argument>
+ <Argument>@TargetDir@/destination/directory</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/copydirectoryoperation/settings.qrc b/tests/auto/installer/copydirectoryoperation/settings.qrc
new file mode 100644
index 000000000..094bd449b
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/settings.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1content.7z</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ <file>data/xmloperationrepository/A/1.0.2-1content.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/copydirectoryoperation/tst_copydirectoryoperation.cpp b/tests/auto/installer/copydirectoryoperation/tst_copydirectoryoperation.cpp
new file mode 100644
index 000000000..a1692095d
--- /dev/null
+++ b/tests/auto/installer/copydirectoryoperation/tst_copydirectoryoperation.cpp
@@ -0,0 +1,217 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <copydirectoryoperation.h>
+#include <packagemanagercore.h>
+
+#include <QDir>
+#include <QFile>
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_copydirectoryoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, repository);
+
+ core->setValue(scTargetDir, installDir);
+ core->installDefaultComponentsSilently();
+
+ // Matches path in component install script
+ QFileInfo targetInfo(installDir + QDir::toNativeSeparators("/directory"));
+ QMap<QString, QByteArray> targetMap;
+ VerifyInstaller::addToFileMap(QDir(targetInfo.absoluteFilePath()), targetInfo, targetMap);
+
+ QFileInfo destinationInfo(installDir + QDir::toNativeSeparators("/destination/directory"));
+ QMap<QString, QByteArray> destinationMap;
+ VerifyInstaller::addToFileMap(QDir(destinationInfo.absoluteFilePath()), destinationInfo, destinationMap);
+
+ QVERIFY(targetMap == destinationMap);
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QVERIFY(!destinationInfo.exists());
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
+ QStringList populateSourceDirectory()
+ {
+ QStringList fileEntries;
+ fileEntries << "file1" << "file2" << ".hidden1" << ".hidden2";
+
+ // Populate source directory
+ foreach (const QString &entry, fileEntries) {
+ QFile file(m_sourcePath + entry);
+ file.open(QFileDevice::ReadWrite);
+ file.close();
+ }
+ return fileEntries;
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_sourcePath = qApp->applicationDirPath() + QDir::toNativeSeparators("/source/");
+ m_destinationPath = generateTemporaryFileName() + QDir::toNativeSeparators("_dest/");
+ }
+
+ void init()
+ {
+ QDir sourceDir;
+ QVERIFY(sourceDir.mkpath(m_sourcePath));
+
+ QDir destinationDir;
+ QVERIFY(destinationDir.mkpath(m_destinationPath));
+ }
+
+ void cleanup()
+ {
+ QVERIFY(QDir(m_sourcePath).removeRecursively());
+ QVERIFY(QDir(m_destinationPath).removeRecursively());
+ }
+
+ void testInvalidArguments()
+ {
+ CopyDirectoryOperation op(nullptr);
+
+ QVERIFY(op.testOperation());
+ op.backup();
+
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in CopyDirectory: "
+ "0 arguments given, 2 or 3 arguments expected in the form: "
+ "<source> <target> [\"forceOverwrite\"]."));
+
+ op.setArguments(QStringList() << "" << "" << "overwrite");
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid argument in CopyDirectory: "
+ "Third argument needs to be forceOverwrite, "
+ "if specified."));
+
+ op.setArguments(QStringList() << "" << "");
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid argument in CopyDirectory: "
+ "Directory \"\" is invalid."));
+ }
+
+ void testCopyDirectoryWithUndo()
+ {
+ const QStringList fileEntries = populateSourceDirectory();
+
+ CopyDirectoryOperation op(nullptr);
+ op.setArguments(QStringList() << m_sourcePath << m_destinationPath);
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+
+ foreach (const QString &entry, fileEntries)
+ QVERIFY(QFile(m_destinationPath + entry).exists());
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+ // Undo will delete the empty destination directory here
+ QVERIFY(!QFileInfo(m_destinationPath).exists());
+ }
+
+
+ void testCopyDirectoryNoUndo()
+ {
+ const QStringList fileEntries = populateSourceDirectory();
+
+ CopyDirectoryOperation op(nullptr);
+ op.setArguments(QStringList() << m_sourcePath << m_destinationPath << "UNDOOPERATION" << "");
+
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+
+ foreach (const QString &entry, fileEntries)
+ QVERIFY(QFile(m_destinationPath + entry).exists());
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+ // Undo will NOT delete the empty destination directory here
+ foreach (const QString &entry, fileEntries)
+ QVERIFY(QFile(m_destinationPath + entry).exists());
+ }
+
+ void testCopyDirectoryOverwrite()
+ {
+ QFile file(m_sourcePath + "file");
+ QVERIFY(file.open(QFileDevice::ReadWrite));
+ file.close();
+
+ file.setFileName(m_destinationPath + "file");
+ QVERIFY(file.open(QFileDevice::ReadWrite));
+ file.close();
+
+ CopyDirectoryOperation op(nullptr);
+
+ op.setArguments(QStringList() << m_sourcePath << m_destinationPath);
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError);
+
+ op.setArguments(QStringList() << m_sourcePath << m_destinationPath << "forceOverwrite");
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ }
+
+ void testCopyDirectoryFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testCopyDirectoryFromComponentXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+
+private:
+ QString m_sourcePath;
+ QString m_destinationPath;
+};
+
+QTEST_MAIN(tst_copydirectoryoperation)
+
+#include "tst_copydirectoryoperation.moc"
diff --git a/tests/auto/installer/copyoperationtest/copyoperationtest.pro b/tests/auto/installer/copyoperationtest/copyoperationtest.pro
index ce4ad42ec..a832fe295 100644
--- a/tests/auto/installer/copyoperationtest/copyoperationtest.pro
+++ b/tests/auto/installer/copyoperationtest/copyoperationtest.pro
@@ -4,3 +4,7 @@ QT -= gui
QT += testlib
SOURCES = tst_copyoperationtest.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/copyoperationtest/data/repository/A/1.0.2-1content.7z b/tests/auto/installer/copyoperationtest/data/repository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..8ba90b13b
--- /dev/null
+++ b/tests/auto/installer/copyoperationtest/data/repository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/copyoperationtest/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/copyoperationtest/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..ae2a965bb
--- /dev/null
+++ b/tests/auto/installer/copyoperationtest/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/copyoperationtest/data/repository/Updates.xml b/tests/auto/installer/copyoperationtest/data/repository/Updates.xml
new file mode 100644
index 000000000..0826afae8
--- /dev/null
+++ b/tests/auto/installer/copyoperationtest/data/repository/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6d7a3e15d11a4d94b81452fc2aa18e705a01c922</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/copyoperationtest/data/xmloperationrepository/A/1.0.2-1content.7z b/tests/auto/installer/copyoperationtest/data/xmloperationrepository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..8ba90b13b
--- /dev/null
+++ b/tests/auto/installer/copyoperationtest/data/xmloperationrepository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/copyoperationtest/data/xmloperationrepository/Updates.xml b/tests/auto/installer/copyoperationtest/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..4ad1e243b
--- /dev/null
+++ b/tests/auto/installer/copyoperationtest/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,25 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6d7a3e15d11a4d94b81452fc2aa18e705a01c922</SHA1>
+ <Operations>
+ <Operation name="Mkdir">
+ <Argument>@TargetDir@/AnotherFolder</Argument>
+ </Operation>
+ <Operation name="Copy">
+ <Argument>@TargetDir@/A.txt</Argument>
+ <Argument>@TargetDir@/AnotherFolder/A.txt</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/copyoperationtest/settings.qrc b/tests/auto/installer/copyoperationtest/settings.qrc
new file mode 100644
index 000000000..094bd449b
--- /dev/null
+++ b/tests/auto/installer/copyoperationtest/settings.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1content.7z</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ <file>data/xmloperationrepository/A/1.0.2-1content.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp b/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp
index e55fc89f4..692fd86d9 100644
--- a/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp
+++ b/tests/auto/installer/copyoperationtest/tst_copyoperationtest.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -25,16 +25,13 @@
** $QT_END_LICENSE$
**
**************************************************************************/
+#include "../shared/packagemanager.h"
-#include <init.h>
#include <updateoperations.h>
#include <utils.h>
+#include <packagemanagercore.h>
-#include <QDir>
-#include <QObject>
#include <QTest>
-#include <QFile>
-#include <QDebug>
using namespace KDUpdater;
using namespace QInstaller;
@@ -43,6 +40,33 @@ class tst_copyoperationtest : public QObject
{
Q_OBJECT
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit(installDir, repository);
+ core->installDefaultComponentsSilently();
+
+ QFile copiedFile(installDir + QDir::separator() + "AnotherFolder/A.txt");
+ QVERIFY(copiedFile.exists());
+ QFile originalFile(installDir + QDir::separator() + "A.txt");
+ QVERIFY(originalFile.exists());
+
+ QByteArray destinationFileHash = QInstaller::calculateHash(copiedFile.fileName(), QCryptographicHash::Sha1);
+ QByteArray testFileHash = QInstaller::calculateHash(originalFile.fileName(), QCryptographicHash::Sha1);
+ QVERIFY(testFileHash == destinationFileHash);
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QVERIFY(!copiedFile.exists());
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
private slots:
void initTestCase()
{
@@ -63,37 +87,48 @@ private slots:
QVERIFY(!op.performOperation());
QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
- QCOMPARE(op.errorString(), QString("Invalid arguments in Copy: "
- "0 arguments given, exactly 2 arguments expected."));
-
+ QCOMPARE(op.errorString(), QString("Invalid arguments in Copy: 0 arguments given, "
+ "2 to 4 arguments expected in the form: <source filename> <destination filename> [UNDOOPERATION, \"\"]."));
}
void testCopySomething_data()
{
- QTest::addColumn<QString>("source");
- QTest::addColumn<QString>("destination");
- QTest::newRow("full path syntax") << qApp->applicationFilePath() << m_testDestinationFilePath;
- QTest::newRow("short destination syntax") << qApp->applicationFilePath() << m_testDestinationPath;
- QTest::newRow("short destination syntax with ending separator") << qApp->applicationFilePath()
- << m_testDestinationPath + QDir::separator();
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QString>("destination");
+ QTest::addColumn<bool>("overrideUndo");
+ QTest::newRow("full path syntax") << qApp->applicationFilePath() << m_testDestinationFilePath << false;
+ QTest::newRow("short destination syntax") << qApp->applicationFilePath() << m_testDestinationPath << false;
+ QTest::newRow("short destination syntax with ending separator") << qApp->applicationFilePath()
+ << m_testDestinationPath + QDir::separator() << false;
+ QTest::newRow("override undo") << qApp->applicationFilePath() << m_testDestinationFilePath << true;
}
void testCopySomething()
{
QFETCH(QString, source);
QFETCH(QString, destination);
+ QFETCH(bool, overrideUndo);
- QVERIFY2(QFileInfo(source).exists(), QString("Source file \"%1\" does not exist.").arg(source).toLatin1());
- CopyOperation op;
- op.setArguments(QStringList() << source << destination);
- op.backup();
- QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY2(QFileInfo::exists(source), QString("Source file \"%1\" does not exist.").arg(source).toLatin1());
+ CopyOperation *op = new CopyOperation();
+ op->setArguments(QStringList() << source << destination);
+ if (overrideUndo)
+ op->setArguments(op->arguments() << QLatin1String("UNDOOPERATION"));
+ op->backup();
+ QVERIFY2(op->performOperation(), op->errorString().toLatin1());
- QVERIFY2(QFileInfo(m_testDestinationFilePath).exists(), QString("Copying from \"%1\" to \"%2\" was "
+ QVERIFY2(QFileInfo::exists(m_testDestinationFilePath), QString("Copying from \"%1\" to \"%2\" was "
"not working: '%3' does not exist").arg(source, destination, m_testDestinationFilePath).toLatin1());
- QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
- QVERIFY2(!QFileInfo(m_testDestinationFilePath).exists(), QString("Undo of copying from \"%1\" to "
- "\"%2\" was not working.").toLatin1());
+ QVERIFY2(op->undoOperation(), op->errorString().toLatin1());
+ if (!overrideUndo) {
+ QVERIFY2(!QFileInfo::exists(m_testDestinationFilePath), QString("Undo of copying from \"%1\" to "
+ "\"%2\" was not working.").toLatin1());
+ } else {
+ QVERIFY(QFileInfo::exists(m_testDestinationFilePath));
+ }
+ QString backupFileName = op->value("backupOfExistingDestination").toString();
+ delete op;
+ QVERIFY(!QFileInfo::exists(backupFileName));
}
void testCopyIfDestinationExist_data()
@@ -134,6 +169,16 @@ private slots:
currentFileHash = QInstaller::calculateHash(m_testDestinationFilePath, QCryptographicHash::Sha1);
QVERIFY(testFileHash == currentFileHash);
}
+
+ void testCopyFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+ void testCopyFromComponentXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+
void init()
{
QVERIFY2(!QFileInfo(m_testDestinationFilePath).exists(), QString("Destination \"%1\" should not exist "
diff --git a/tests/auto/installer/createdesktopentryoperation/createdesktopentryoperation.pro b/tests/auto/installer/createdesktopentryoperation/createdesktopentryoperation.pro
new file mode 100644
index 000000000..1f0b98429
--- /dev/null
+++ b/tests/auto/installer/createdesktopentryoperation/createdesktopentryoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_createdesktopentryoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/createdesktopentryoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/createdesktopentryoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..2905c12be
--- /dev/null
+++ b/tests/auto/installer/createdesktopentryoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/createdesktopentryoperation/data/repository/Updates.xml b/tests/auto/installer/createdesktopentryoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..ad6c49c81
--- /dev/null
+++ b/tests/auto/installer/createdesktopentryoperation/data/repository/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>0746c8292e3799aac4a534a0a1a58d42ef24ed43</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/createdesktopentryoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/createdesktopentryoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..a5131552d
--- /dev/null
+++ b/tests/auto/installer/createdesktopentryoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,18 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Operations>
+ <Operation name="CreateDesktopEntry">
+ <Argument>org.qtproject.ifw-test.desktop</Argument>
+ <Argument>Type=Application\nName=Test\nVersion=1.0</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/createdesktopentryoperation/settings.qrc b/tests/auto/installer/createdesktopentryoperation/settings.qrc
new file mode 100644
index 000000000..04a7daf71
--- /dev/null
+++ b/tests/auto/installer/createdesktopentryoperation/settings.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/createdesktopentryoperation/tst_createdesktopentryoperation.cpp b/tests/auto/installer/createdesktopentryoperation/tst_createdesktopentryoperation.cpp
new file mode 100644
index 000000000..c73e7cc03
--- /dev/null
+++ b/tests/auto/installer/createdesktopentryoperation/tst_createdesktopentryoperation.cpp
@@ -0,0 +1,179 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+
+#include <createdesktopentryoperation.h>
+
+#include <packagemanagercore.h>
+#include <binarycontent.h>
+#include <settings.h>
+#include <fileutils.h>
+#include <init.h>
+#include <component.h>
+
+#include <QObject>
+#include <QTest>
+#include <QFile>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_createdesktopentryoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, repository);
+
+ core->installDefaultComponentsSilently();
+
+ CreateDesktopEntryOperation *createDesktopEntryOp = nullptr;
+ OperationList operations = core->componentByName("A")->operations();
+ foreach (Operation *op, operations) {
+ if (op->name() == QLatin1String("CreateDesktopEntry"))
+ createDesktopEntryOp = dynamic_cast<CreateDesktopEntryOperation *>(op);
+ }
+ QVERIFY(createDesktopEntryOp);
+
+ QString entryFileName = createDesktopEntryOp->absoluteFileName();
+ QVERIFY(QFileInfo(entryFileName).exists());
+ if (QFileInfo(createDesktopEntryOp->arguments().first()).isRelative()) {
+ QStringList directories = QString::fromLocal8Bit(qgetenv("XDG_DATA_HOME"))
+ .split(QLatin1Char(':'), Qt::SkipEmptyParts);
+ // Default path if XDG_DATA_HOME is not set
+ directories.append(QDir::home().absoluteFilePath(QLatin1String(".local/share")));
+ // Default path if run as root
+ directories.append(QLatin1String("/usr/local/share"));
+ bool validPath = false;
+ foreach (const QString &dir, directories) {
+ // Desktop entry should be in one of the expected locations
+ if (QFileInfo(entryFileName).absolutePath() == QDir(dir).absoluteFilePath("applications")) {
+ validPath = true;
+ break;
+ }
+ }
+ QVERIFY(validPath);
+ }
+ core->setPackageManager();
+ core->commitSessionOperations();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QVERIFY2(!QFileInfo(entryFileName).exists(), "Please make sure there "
+ "does not exist a desktop entry with the same name.");
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_desktopEntryContents = "Type=Application\nName=Test\nVersion=1.0";
+ }
+
+ void testMissingArguments()
+ {
+ CreateDesktopEntryOperation op(nullptr);
+
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in CreateDesktopEntry: "
+ "0 arguments given, exactly 2 arguments expected."));
+ }
+
+ void testCreateDesktopEntry_data()
+ {
+ QTest::addColumn<QString>("filename");
+ QTest::newRow("relative") << "entry";
+ QTest::newRow("absolute") << qApp->applicationDirPath() + "/entry";
+ }
+
+ void testCreateDesktopEntry()
+ {
+ QFETCH(QString, filename);
+
+ CreateDesktopEntryOperation op(nullptr);
+ op.setArguments(QStringList() << filename << m_desktopEntryContents);
+
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY(QFileInfo().exists(op.absoluteFileName()));
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo().exists(op.absoluteFileName()));
+ }
+
+ void testBackupExistingEntry()
+ {
+ QString filename = qApp->applicationDirPath() + "/entry";
+
+ CreateDesktopEntryOperation op(nullptr);
+ op.setArguments(QStringList() << filename << m_desktopEntryContents);
+
+ op.backup();
+ QVERIFY(!op.hasValue("backupOfExistingDesktopEntry"));
+
+ QFile existingEntry(filename);
+ QVERIFY(existingEntry.open(QFileDevice::ReadWrite) && existingEntry.exists());
+ existingEntry.close();
+
+ op.backup();
+ QVERIFY(op.hasValue("backupOfExistingDesktopEntry"));
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo().exists(op.value("backupOfExistingDesktopEntry").toString()));
+ QVERIFY(QFileInfo().exists(filename));
+
+ QVERIFY(QFile(filename).remove());
+ }
+
+ void testDesktopEntryFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testDesktopEntryFromXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+
+private:
+ QString m_desktopEntryContents;
+};
+
+QTEST_MAIN(tst_createdesktopentryoperation)
+
+#include "tst_createdesktopentryoperation.moc"
diff --git a/tests/auto/installer/createoffline/createoffline.pro b/tests/auto/installer/createoffline/createoffline.pro
new file mode 100644
index 000000000..bdb050f4d
--- /dev/null
+++ b/tests/auto/installer/createoffline/createoffline.pro
@@ -0,0 +1,9 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_createoffline.cpp
+
+RESOURCES += settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-license/2020-12-01-1511_meta.7z b/tests/auto/installer/createoffline/data/repository-bothmeta-license/2020-12-01-1511_meta.7z
new file mode 100644
index 000000000..31ffc5764
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-license/2020-12-01-1511_meta.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-license/Updates.xml b/tests/auto/installer/createoffline/data/repository-bothmeta-license/Updates.xml
new file mode 100644
index 000000000..064fc6529
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-license/Updates.xml
@@ -0,0 +1,22 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>org.qtproject.ifw.example.licenseagreement</Name>
+ <DisplayName>README (requires license agreement)</DisplayName>
+ <Description>README can only be installed if the user agrees to the licenses.</Description>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Version>1.0.0-1</Version>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="282" OS="Any" UncompressedSize="116"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Licenses>
+ <License name="Creative Commons (CC0 1.0)" file="cc0.txt"/>
+ <License name="GNU GENERAL PUBLIC LICENSE Version 3" file="gpl3.txt"/>
+ </Licenses>
+ <SHA1>6d6a4cead84562b7034fcf1b9975779f1f030151</SHA1>
+ </PackageUpdate>
+ <SHA1>6d6a4cead84562b7034fcf1b9975779f1f030151</SHA1>
+ <MetadataName>2020-12-01-1511_meta.7z</MetadataName>
+</Updates>
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z b/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z
new file mode 100644
index 000000000..d80146aa8
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z.sha1 b/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..49df32fea
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+192106030e00704e880fb729c3f7bed8ced8db92 \ No newline at end of file
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1meta.7z b/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1meta.7z
new file mode 100644
index 000000000..31ffc5764
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/2020-12-01-1524_meta.7z b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/2020-12-01-1524_meta.7z
new file mode 100644
index 000000000..93f95c1d7
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/2020-12-01-1524_meta.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/Updates.xml b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/Updates.xml
new file mode 100644
index 000000000..cc0ae0206
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/Updates.xml
@@ -0,0 +1,20 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>or.qtproject.ifw.example.openreadme</Name>
+ <DisplayName>Open readme</DisplayName>
+ <Description>Show checkbox asking whether to open Readme at the end</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>installscript.qs</Script>
+ <UpdateFile UncompressedSize="49" OS="Any" CompressedSize="215"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <UserInterfaces>readmecheckboxform.ui</UserInterfaces>
+ <SHA1>9b8977a50cb49a77a6ff037d776b73c341412a25</SHA1>
+ </PackageUpdate>
+ <SHA1>9b8977a50cb49a77a6ff037d776b73c341412a25</SHA1>
+ <MetadataName>2020-12-01-1524_meta.7z</MetadataName>
+</Updates>
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z
new file mode 100644
index 000000000..98154743c
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z.sha1 b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..154c20383
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+27cdf6cc53d2317aa2a869cb3f93e7a54c489b5f \ No newline at end of file
diff --git a/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1meta.7z b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1meta.7z
new file mode 100644
index 000000000..93f95c1d7
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z b/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z
new file mode 100644
index 000000000..1c5ff001a
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z.sha1 b/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z.sha1
new file mode 100644
index 000000000..b36346655
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z.sha1
@@ -0,0 +1 @@
+5097e37368b44fc5242f3bb2fce08f5ade6c4c40 \ No newline at end of file
diff --git a/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1meta.7z b/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..408550be6
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/Updates.xml b/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/Updates.xml
new file mode 100644
index 000000000..d3b180e43
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-componentmeta-emptymetafile/Updates.xml
@@ -0,0 +1,16 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile UncompressedSize="72" OS="Any" CompressedSize="222"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>65c0db5bcf28139d434dce0e21674e33c87ab6d9</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/createoffline/data/repository-componentmeta-script/Updates.xml b/tests/auto/installer/createoffline/data/repository-componentmeta-script/Updates.xml
new file mode 100644
index 000000000..42458e7ce
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-componentmeta-script/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>org.qtproject.ifw.example</Name>
+ <DisplayName>README.txt</DisplayName>
+ <Description>A README.txt, accessible through a start menu entry.</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>installscript.qs</Script>
+ <UpdateFile UncompressedSize="131" CompressedSize="297" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>08c2a05d861543e88a8808f576d5c731e0301ab4</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z b/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z
new file mode 100644
index 000000000..40ebd637a
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha1 b/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..d1c96e12b
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+d9ad62d190d93c92175741c02d17aa6c39b0e03d \ No newline at end of file
diff --git a/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1meta.7z b/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1meta.7z
new file mode 100644
index 000000000..f35ec6071
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-missingdependency/Updates.xml b/tests/auto/installer/createoffline/data/repository-missingdependency/Updates.xml
new file mode 100644
index 000000000..2ec3a5ac4
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-missingdependency/Updates.xml
@@ -0,0 +1,22 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>example.with.unstable.dependency</Name>
+ <DisplayName>README.txt</DisplayName>
+ <Description>A README.txt, accessible through a start menu entry.</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Default>false</Default>
+ <Dependencies>missing.dependency.component</Dependencies>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>example.without.unstable.dependency</Name>
+ <DisplayName>README.txt</DisplayName>
+ <Description>A README.txt, accessible through a start menu entry.</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2013-01-01</ReleaseDate>
+ <Default>false</Default>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/2020-12-01-1519_meta.7z b/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/2020-12-01-1519_meta.7z
new file mode 100644
index 000000000..e96ed9ec0
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/2020-12-01-1519_meta.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/Updates.xml b/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/Updates.xml
new file mode 100644
index 000000000..e0826ae86
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/Updates.xml
@@ -0,0 +1,18 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>org.qtproject.ifw.example</Name>
+ <DisplayName>README.txt</DisplayName>
+ <Description>A README.txt, accessible through a start menu entry.</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2021-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>installscript.qs</Script>
+ <UpdateFile OS="Any" CompressedSize="297" UncompressedSize="131"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+ <SHA1>70ff1e1062ada01ea698a908f7549fcb826f17e1</SHA1>
+ <MetadataName>2020-12-01-1519_meta.7z</MetadataName>
+</Updates>
diff --git a/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z b/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z
new file mode 100644
index 000000000..40ebd637a
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha1 b/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..d1c96e12b
--- /dev/null
+++ b/tests/auto/installer/createoffline/data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+d9ad62d190d93c92175741c02d17aa6c39b0e03d \ No newline at end of file
diff --git a/tests/auto/installer/createoffline/settings.qrc b/tests/auto/installer/createoffline/settings.qrc
new file mode 100644
index 000000000..4b7666b4a
--- /dev/null
+++ b/tests/auto/installer/createoffline/settings.qrc
@@ -0,0 +1,32 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository-bothmeta-license/2020-12-01-1511_meta.7z</file>
+ <file>data/repository-bothmeta-license/Updates.xml</file>
+ <file>data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z</file>
+ <file>data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1content.7z.sha1</file>
+ <file>data/repository-bothmeta-license/org.qtproject.ifw.example.licenseagreement/1.0.0-1meta.7z</file>
+
+ <file>data/repository-bothmeta-userinteface/2020-12-01-1524_meta.7z</file>
+ <file>data/repository-bothmeta-userinteface/Updates.xml</file>
+ <file>data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z</file>
+ <file>data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1content.7z.sha1</file>
+ <file>data/repository-bothmeta-userinteface/or.qtproject.ifw.example.openreadme/1.0.0-1meta.7z</file>
+
+ <file>data/repository-componentmeta-script/Updates.xml</file>
+ <file>data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z</file>
+ <file>data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha1</file>
+ <file>data/repository-componentmeta-script/org.qtproject.ifw.example/1.0.0-1meta.7z</file>
+
+ <file>data/repository-missingdependency/Updates.xml</file>
+
+ <file>data/repository-unifiedmeta-script/2020-12-01-1519_meta.7z</file>
+ <file>data/repository-unifiedmeta-script/Updates.xml</file>
+ <file>data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z</file>
+ <file>data/repository-unifiedmeta-script/org.qtproject.ifw.example/1.0.0-1content.7z.sha1</file>
+
+ <file>data/repository-componentmeta-emptymetafile/Updates.xml</file>
+ <file>data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z</file>
+ <file>data/repository-componentmeta-emptymetafile/A/1.0.2-1content.7z.sha1</file>
+ <file>data/repository-componentmeta-emptymetafile/A/1.0.2-1meta.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/createoffline/tst_createoffline.cpp b/tests/auto/installer/createoffline/tst_createoffline.cpp
new file mode 100644
index 000000000..607f9b7cc
--- /dev/null
+++ b/tests/auto/installer/createoffline/tst_createoffline.cpp
@@ -0,0 +1,176 @@
+/**************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+
+#include <packagemanagercore.h>
+#include <errors.h>
+
+#include <QFile>
+#include <QTest>
+
+using namespace QInstaller;
+
+class tst_CreateOffline : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase()
+ {
+ // Need to provide a replacement base binary as we are not running actual installer
+#ifdef Q_OS_WIN
+ m_installerBase = "../../../../bin/installerbase.exe";
+#else
+ m_installerBase = "../../../../bin/installerbase";
+#endif
+ if (!QFile(m_installerBase).exists()) {
+ QSKIP("No \"installerbase\" binary found in source tree. This can be "
+ "the case if this is an out of sources build or the binaries are "
+ "installed to a location with a different path prefix.");
+ }
+ }
+
+ void init()
+ {
+ // Get new target directory for each test function
+ m_targetDir = QInstaller::generateTemporaryFileName();
+ }
+
+ void cleanup()
+ {
+ QDir dir(m_targetDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
+ void testCreateOfflineInstaller_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QString>("component");
+ QTest::addColumn<PackageManagerCore::Status>("expectedStatus");
+ QTest::newRow("Both metaformats | License")
+ << ":///data/repository-bothmeta-license" << "org.qtproject.ifw.example.licenseagreement"
+ << PackageManagerCore::Success;
+ QTest::newRow("Both metaformats | UserInterface")
+ << ":///data/repository-bothmeta-userinteface" << "or.qtproject.ifw.example.openreadme"
+ << PackageManagerCore::Success;
+ QTest::newRow("Component metaformat | Script")
+ << ":///data/repository-componentmeta-script" << "org.qtproject.ifw.example"
+ << PackageManagerCore::Success;
+ QTest::newRow("Unified metaformat | Script")
+ << ":///data/repository-unifiedmeta-script" << "org.qtproject.ifw.example"
+ << PackageManagerCore::Success;
+ QTest::newRow("Component metaformat | Empty component meta-archive")
+ << ":///data/repository-componentmeta-emptymetafile" << "A"
+ << PackageManagerCore::Success;
+ QTest::newRow("Non-existing component")
+ << ":///data/repository-unifiedmeta-script" << "a.dummy.component"
+ << PackageManagerCore::Canceled;
+ QTest::newRow("Invalid repository")
+ << ":///data/repository-invalid" << "a.dummy.component"
+ << PackageManagerCore::Canceled;
+ }
+
+ void testCreateOfflineInstaller()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QString, component);
+ QFETCH(PackageManagerCore::Status, expectedStatus);
+
+ QScopedPointer<PackageManagerCore> core(
+ PackageManager::getPackageManagerWithInit(m_targetDir, repository));
+ core->setCommandLineInstance(true);
+ core->setOfflineBaseBinary(m_installerBase);
+ core->setOfflineBinaryName("ifw_test_offline");
+ core->setAutoAcceptLicenses();
+
+ // Replace the custom message handler installed in QInstaller::init() to suppress all output
+ qInstallMessageHandler(silentTestMessageHandler);
+
+ QCOMPARE(expectedStatus, core->createOfflineInstaller(QStringList() << component));
+
+ if (expectedStatus == PackageManagerCore::Success) {
+#ifdef Q_OS_LINUX
+ QVERIFY(QFile::exists(m_targetDir + QDir::separator() + "ifw_test_offline"));
+#elif defined Q_OS_MACOS
+ QVERIFY(QFile::exists(m_targetDir + QDir::separator() + "ifw_test_offline.dmg"));
+#elif defined Q_OS_WIN
+ QVERIFY(QFile::exists(m_targetDir + QDir::separator() + "ifw_test_offline.exe"));
+#endif
+ }
+ }
+
+ void testCreateOfflineWithUnstableComponent_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QString>("component");
+ QTest::addColumn<bool>("allowUnstable");
+ QTest::addColumn<PackageManagerCore::Status>("expectedStatus");
+ QTest::newRow("Allow unstable | Missing dependency with selected component")
+ << ":///data/repository-missingdependency" << "example.with.unstable.dependency"
+ << true << PackageManagerCore::Canceled;
+ QTest::newRow("Disallow unstable | Missing dependency with selected component")
+ << ":///data/repository-missingdependency" << "example.with.unstable.dependency"
+ << false << PackageManagerCore::Canceled;
+ QTest::newRow("Allow unstable | Missing dependency with other component")
+ << ":///data/repository-missingdependency" << "example.without.unstable.dependency"
+ << true << PackageManagerCore::Success;
+ QTest::newRow("Disallow unstable | Missing dependency with other component")
+ << ":///data/repository-missingdependency" << "example.without.unstable.dependency"
+ << false << PackageManagerCore::Canceled;
+ }
+
+ void testCreateOfflineWithUnstableComponent()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QString, component);
+ QFETCH(bool, allowUnstable);
+ QFETCH(PackageManagerCore::Status, expectedStatus);
+
+ QScopedPointer<PackageManagerCore> core(
+ PackageManager::getPackageManagerWithInit(m_targetDir, repository));
+ core->setCommandLineInstance(true);
+ core->setOfflineBaseBinary(m_installerBase);
+ core->setOfflineBinaryName("ifw_test_offline");
+ core->settings().setAllowUnstableComponents(allowUnstable);
+ core->autoAcceptMessageBoxes();
+
+ // Replace the custom message handler installed in QInstaller::init() to suppress all output
+ qInstallMessageHandler(silentTestMessageHandler);
+
+ QCOMPARE(expectedStatus, core->createOfflineInstaller(QStringList() << component));
+ }
+
+private:
+ QString m_targetDir;
+ QString m_installerBase;
+};
+
+QTEST_GUILESS_MAIN(tst_CreateOffline)
+
+#include "tst_createoffline.moc"
diff --git a/tests/auto/installer/createshortcutoperation/createshortcutoperation.pro b/tests/auto/installer/createshortcutoperation/createshortcutoperation.pro
new file mode 100644
index 000000000..c57bcfb98
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/createshortcutoperation.pro
@@ -0,0 +1,9 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_createshortcutoperation.cpp
+
+RESOURCES += \
+ settings.qrc
diff --git a/tests/auto/installer/createshortcutoperation/data/repository/A/1.0.2-1content.7z b/tests/auto/installer/createshortcutoperation/data/repository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..8ba90b13b
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/data/repository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/createshortcutoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/createshortcutoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..17eae879d
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/createshortcutoperation/data/repository/Updates.xml b/tests/auto/installer/createshortcutoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..d1909d355
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/data/repository/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component for CreateShortcutOperation</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6d7a3e15d11a4d94b81452fc2aa18e705a01c922</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/createshortcutoperation/data/xmloperationrepository/A/1.0.2-1content.7z b/tests/auto/installer/createshortcutoperation/data/xmloperationrepository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..8ba90b13b
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/data/xmloperationrepository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/createshortcutoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/createshortcutoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..a7d287d4d
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,26 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6d7a3e15d11a4d94b81452fc2aa18e705a01c922</SHA1>
+ <Operations>
+ <Operation name="CreateShortcut">
+ <Argument>@TargetDir@/A.txt</Argument>
+ <Argument>@StartMenuDir@/A.lnk</Argument>
+ <Argument>workingDirectory=@TargetDir@</Argument>
+ <Argument>iconPath=%SystemRoot%/system32/SHELL32.dl</Argument>
+ <Argument>iconId=2</Argument>
+ <Argument>description=Open A file</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/createshortcutoperation/installer-config/config.xml b/tests/auto/installer/createshortcutoperation/installer-config/config.xml
new file mode 100644
index 000000000..c201d4fa5
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/installer-config/config.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Installer>
+ <Name>test</Name>
+ <Version>1.0.0</Version>
+ <StartMenuDir>Qt Installer Framework Unit Test</StartMenuDir>
+</Installer>
diff --git a/tests/auto/installer/createshortcutoperation/settings.qrc b/tests/auto/installer/createshortcutoperation/settings.qrc
new file mode 100644
index 000000000..d2365cab3
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/settings.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1content.7z</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ <file>data/xmloperationrepository/A/1.0.2-1content.7z</file>
+ </qresource>
+ <qresource prefix="/metadata">
+ <file>installer-config/config.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/createshortcutoperation/tst_createshortcutoperation.cpp b/tests/auto/installer/createshortcutoperation/tst_createshortcutoperation.cpp
new file mode 100644
index 000000000..a08567d64
--- /dev/null
+++ b/tests/auto/installer/createshortcutoperation/tst_createshortcutoperation.cpp
@@ -0,0 +1,117 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include <init.h>
+#include <createshortcutoperation.h>
+#include <utils.h>
+#include <binarycontent.h>
+#include <packagemanagercore.h>
+#include <settings.h>
+#include <fileutils.h>
+
+#include <QDir>
+#include <QObject>
+#include <QTest>
+#include <QFile>
+#include <qsettingswrapper.h>
+#include <QDebug>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_createshortcutoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QInstaller::init();
+ QScopedPointer<PackageManagerCore> core(new PackageManagerCore(BinaryContent::MagicInstallerMarker,
+ QList<OperationBlob> (), QString(), QString(), Protocol::DefaultAuthorizationKey,
+ Protocol::Mode::Production, QHash<QString, QString>(), true));
+
+ core->disableWriteMaintenanceTool();
+ core->setAutoConfirmCommand();
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(repository);
+ repoList.insert(repo);
+ core->settings().setDefaultRepositories(repoList);
+
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ core->setValue(scTargetDir, installDir);
+ core->installDefaultComponentsSilently();
+
+ QSettingsWrapper user(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\"
+ "CurrentVersion\\Explorer\\User Shell Folders"), QSettings::NativeFormat);
+ //Replace %USERS% from "Programs"
+ const QString programs = replaceWindowsEnvironmentVariables(user.value(QLatin1String("Programs"), QString()).toString());
+ const QString startMenuDir = programs + QDir::separator() + "Qt Installer Framework Unit Test";
+ QCOMPARE(startMenuDir, core->value("StartMenuDir"));
+
+ QString linkLocation = core->value("StartMenuDir") + QDir::separator() + "A.lnk";
+ QFile file(linkLocation);
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ file.close();
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QVERIFY(!QFile::exists(linkLocation));
+ }
+
+private slots:
+ void testMissingArguments()
+ {
+ CreateShortcutOperation op;
+
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in CreateShortcut: 0 arguments given,"
+ " 2 or 3 arguments expected in the form: <target> <link location> "
+ "[target arguments] [\"workingDirectory=...\"] [\"iconPath=...\"] "
+ "[\"iconId=...\"] [\"description=...\"]."));
+ }
+
+ void testCreateShortcutFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testCreateShortcutFromXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+};
+
+QTEST_MAIN(tst_createshortcutoperation)
+
+#include "tst_createshortcutoperation.moc"
diff --git a/tests/auto/installer/deleteoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/deleteoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..c87d8642e
--- /dev/null
+++ b/tests/auto/installer/deleteoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/deleteoperation/data/repository/Updates.xml b/tests/auto/installer/deleteoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..5a8b28f38
--- /dev/null
+++ b/tests/auto/installer/deleteoperation/data/repository/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>e8b8ce98862d463c855609ed8e139eda17092cc6</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/deleteoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/deleteoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..6856014b9
--- /dev/null
+++ b/tests/auto/installer/deleteoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Operations>
+ <Operation name="Delete">
+ <Argument>@TargetDir@/test</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/deleteoperation/deleteoperation.pro b/tests/auto/installer/deleteoperation/deleteoperation.pro
new file mode 100644
index 000000000..f22867965
--- /dev/null
+++ b/tests/auto/installer/deleteoperation/deleteoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_deleteoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/deleteoperation/settings.qrc b/tests/auto/installer/deleteoperation/settings.qrc
new file mode 100644
index 000000000..04a7daf71
--- /dev/null
+++ b/tests/auto/installer/deleteoperation/settings.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/deleteoperation/tst_deleteoperation.cpp b/tests/auto/installer/deleteoperation/tst_deleteoperation.cpp
new file mode 100644
index 000000000..43ea52407
--- /dev/null
+++ b/tests/auto/installer/deleteoperation/tst_deleteoperation.cpp
@@ -0,0 +1,153 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+
+#include <updateoperations.h>
+#include <packagemanagercore.h>
+#include <settings.h>
+#include <utils.h>
+
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_deleteoperation : public QObject
+{
+ Q_OBJECT
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit(installDir, repository);
+
+ // Matches filename in component install script
+ QFile file(installDir + QDir::toNativeSeparators("/test"));
+ QVERIFY(file.open(QIODevice::ReadWrite));
+ file.close();
+
+ core->installDefaultComponentsSilently();
+ QVERIFY(!file.exists());
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QVERIFY(file.exists());
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
+private slots:
+ void testMissingArguments()
+ {
+ DeleteOperation op;
+
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in Delete: 0 arguments given, 1 to 3 arguments expected in the form: <file to remove> [UNDOOPERATION, \"\"]."));
+
+ op.setArguments(QStringList() << "");
+ QTest::ignoreMessage(QtWarningMsg, "QFile::copy: Empty or null file name");
+ op.backup();
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError);
+ QCOMPARE(op.errorString(), QString("Cannot create backup of file \"\": Unknown error"));
+
+ // Returns true with empty file argument but does not do anything
+ QVERIFY(op.performOperation());
+ }
+
+ void testDeleteRestore_data()
+ {
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("overrideUndo");
+ QTest::newRow("relative") << "test" << false;
+ QTest::newRow("absolute") << qApp->applicationDirPath() + QDir::toNativeSeparators("/test") << false;
+ QTest::newRow("no undo") << "test" << true;
+ }
+
+ void testDeleteRestore()
+ {
+ QFETCH(QString, path);
+ QFETCH(bool, overrideUndo);
+
+ QByteArray testString("Generated by QTest\n");
+ QFile testFile(path);
+ QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text));
+ QTextStream out(&testFile);
+ out << testString;
+ testFile.close();
+
+ QVERIFY(QFileInfo::exists(path));
+ QByteArray testFileHash = QInstaller::calculateHash(path, QCryptographicHash::Sha1);
+
+ DeleteOperation *op = new DeleteOperation();
+ op->setArguments(QStringList() << path);
+ if (overrideUndo)
+ op->setArguments(op->arguments() << QLatin1String("UNDOOPERATION"));
+
+ op->backup();
+ QVERIFY(QFileInfo::exists(op->value("backupOfExistingFile").toString()));
+
+ QVERIFY2(op->performOperation(), op->errorString().toLatin1());
+ QVERIFY(!QFileInfo::exists(path));
+
+ QVERIFY2(op->undoOperation(), op->errorString().toLatin1());
+ if (!overrideUndo) {
+ QByteArray restoredFileHash = QInstaller::calculateHash(path, QCryptographicHash::Sha1);
+ QVERIFY(testFileHash == restoredFileHash);
+ } else {
+ QVERIFY(!QFileInfo::exists(path));
+ }
+
+ QString backupFileName = op->value("backupOfExistingFile").toString();
+ delete op;
+ QVERIFY(!QFileInfo::exists(backupFileName));
+ QCOMPARE(QFile(path).remove(), !overrideUndo);
+ }
+
+ void testDeleteFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testDeleteFromXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+};
+
+QTEST_MAIN(tst_deleteoperation)
+
+#include "tst_deleteoperation.moc"
diff --git a/tests/auto/installer/elevatedexecuteoperation/elevatedexecuteoperation.pro b/tests/auto/installer/elevatedexecuteoperation/elevatedexecuteoperation.pro
new file mode 100644
index 000000000..9ac3f260a
--- /dev/null
+++ b/tests/auto/installer/elevatedexecuteoperation/elevatedexecuteoperation.pro
@@ -0,0 +1,8 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib qml
+
+SOURCES = tst_elevatedexecuteoperation.cpp
+
+DEFINES += "QMAKE_BINARY=$$fromNativeSeparators($$QMAKE_BINARY)"
diff --git a/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp b/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp
new file mode 100644
index 000000000..ef185a5cf
--- /dev/null
+++ b/tests/auto/installer/elevatedexecuteoperation/tst_elevatedexecuteoperation.cpp
@@ -0,0 +1,67 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include <packagemanagercore.h>
+#include <elevatedexecuteoperation.h>
+
+#include <QTest>
+
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+
+using namespace QInstaller;
+
+class tst_elevatedexecuteoperation : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testExecuteOperation()
+ {
+ m_core.setValue(QLatin1String("QMAKE_BINARY"), QUOTE(QMAKE_BINARY));
+ m_core.setValue(QLatin1String("QMAKE_BINARY_OLD"), QLatin1String("FAKE_QMAKE"));
+ ElevatedExecuteOperation operation(&m_core);
+ operation.setArguments(QStringList() << QLatin1String("UNDOEXECUTE") << QLatin1String("FAKE_QMAKE") << QLatin1String("-v"));
+
+ QTest::ignoreMessage(QtDebugMsg, "\"FAKE_QMAKE\" started, arguments: \"-v\"");
+ QString message = "Failed to run undo operation \"Execute\" for component . Trying again with arguments %1, -v";
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(QUOTE(QMAKE_BINARY))));
+ message = "\"%1\" started, arguments: \"-v\"";
+ QTest::ignoreMessage(QtDebugMsg, qPrintable(message.arg(QUOTE(QMAKE_BINARY))));
+
+ QCOMPARE(operation.undoOperation(), true);
+ QCOMPARE(Operation::Error(operation.error()), Operation::NoError);
+ }
+
+private:
+ PackageManagerCore m_core;
+};
+
+QTEST_MAIN(tst_elevatedexecuteoperation)
+
+#include "tst_elevatedexecuteoperation.moc"
diff --git a/tests/auto/installer/environmentvariableoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/environmentvariableoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..26b9ed692
--- /dev/null
+++ b/tests/auto/installer/environmentvariableoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/environmentvariableoperation/data/repository/Updates.xml b/tests/auto/installer/environmentvariableoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..5bcd58c69
--- /dev/null
+++ b/tests/auto/installer/environmentvariableoperation/data/repository/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>4b7b52af2d838389a7404c553da74705fc106493</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/environmentvariableoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/environmentvariableoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..9c33caf6d
--- /dev/null
+++ b/tests/auto/installer/environmentvariableoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,25 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Operations>
+ <Operation name="EnvironmentVariable">
+ <Argument>IFW_UNIT_TEST_LOCAL</Argument>
+ <Argument>IFW_UNIT_TEST_VALUE</Argument>
+ <Argument>false</Argument>
+ </Operation>
+ <Operation name="EnvironmentVariable">
+ <Argument>IFW_UNIT_TEST_PERSISTENT</Argument>
+ <Argument>IFW_UNIT_TEST_PERSISTENT_VALUE</Argument>
+ <Argument>true</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/environmentvariableoperation/environmentvariableoperation.pro b/tests/auto/installer/environmentvariableoperation/environmentvariableoperation.pro
new file mode 100644
index 000000000..77f566d59
--- /dev/null
+++ b/tests/auto/installer/environmentvariableoperation/environmentvariableoperation.pro
@@ -0,0 +1,11 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_environmentvariableoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
+
diff --git a/tests/auto/installer/environmentvariableoperation/settings.qrc b/tests/auto/installer/environmentvariableoperation/settings.qrc
new file mode 100644
index 000000000..04a7daf71
--- /dev/null
+++ b/tests/auto/installer/environmentvariableoperation/settings.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/environmentvariableoperation/tst_environmentvariableoperation.cpp b/tests/auto/installer/environmentvariableoperation/tst_environmentvariableoperation.cpp
new file mode 100644
index 000000000..4afbc709c
--- /dev/null
+++ b/tests/auto/installer/environmentvariableoperation/tst_environmentvariableoperation.cpp
@@ -0,0 +1,184 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+
+#include <environmentvariablesoperation.h>
+#include <environment.h>
+#include <packagemanagercore.h>
+
+#include <QSettings>
+#include <QTest>
+
+using namespace QInstaller;
+using namespace KDUpdater;
+
+class tst_environmentvariableoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (installDir, repository));
+ core->installDefaultComponentsSilently();
+
+ QVERIFY(m_settings->value("IFW_UNIT_TEST_LOCAL").toString().isEmpty());
+
+ // Persistent is in settings in Windows platform only, otherwise it is written to local env.
+#ifdef Q_OS_WIN
+ QCOMPARE(m_settings->value("IFW_UNIT_TEST_PERSISTENT").toString(), QLatin1String("IFW_UNIT_TEST_PERSISTENT_VALUE"));
+#else
+ QCOMPARE(Environment::instance().value("IFW_UNIT_TEST_PERSISTENT"), QLatin1String("IFW_UNIT_TEST_PERSISTENT_VALUE"));
+#endif
+ QCOMPARE(Environment::instance().value("IFW_UNIT_TEST_LOCAL"), QLatin1String("IFW_UNIT_TEST_VALUE"));
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QVERIFY(m_settings->value("IFW_UNIT_TEST_PERSISTENT").toString().isEmpty());
+ QVERIFY(Environment::instance().value("IFW_UNIT_TEST_LOCAL").isEmpty());
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_key = "IFW_TestKey";
+ m_value = "IFW_TestValue";
+ m_oldValue = "IFW_TestOldValue";
+ m_settings = new QSettings("HKEY_CURRENT_USER\\Environment", QSettings::NativeFormat);
+ }
+
+ void cleanup()
+ {
+ m_settings->remove(m_key);
+ m_settings->remove("IFW_UNIT_TEST_PERSISTENT"); //Added from script
+ }
+
+ void testPersistentNonSystem()
+ {
+ #ifndef Q_OS_WIN
+ QSKIP("This operation only works on Windows");
+ #endif
+ EnvironmentVariableOperation op(nullptr);
+ op.setArguments( QStringList() << m_key
+ << m_value
+ << QLatin1String("true")
+ << QLatin1String("false"));
+ const bool ok = op.performOperation();
+
+ QVERIFY2(ok, qPrintable(op.errorString()));
+
+ QCOMPARE(m_value, m_settings->value(m_key).toString());
+
+ QVERIFY(op.undoOperation());
+ QVERIFY(m_settings->value(m_key).toString().isEmpty());
+ }
+
+ void testNonPersistentNonSystem()
+ {
+ EnvironmentVariableOperation op(nullptr);
+ op.setArguments( QStringList() << m_key
+ << m_value
+ << QLatin1String("false")
+ << QLatin1String("false"));
+ const bool ok = op.performOperation();
+
+ QVERIFY2(ok, qPrintable(op.errorString()));
+
+ //Make sure it is not written to env variable
+ QString comp = QString::fromLocal8Bit(qgetenv(qPrintable(m_key)));
+ QVERIFY(comp.isEmpty());
+
+ QCOMPARE(m_value, Environment::instance().value(m_key));
+ }
+
+ void testPersistentNonSystemOldValue()
+ {
+ #ifndef Q_OS_WIN
+ QSKIP("This operation only works on Windows");
+ #endif
+ m_settings->setValue(m_key, m_oldValue);
+
+ EnvironmentVariableOperation op(nullptr);
+ op.setArguments( QStringList() << m_key
+ << m_value
+ << QLatin1String("true")
+ << QLatin1String("false"));
+ const bool ok = op.performOperation();
+
+ QVERIFY2(ok, qPrintable(op.errorString()));
+
+ QCOMPARE(m_value, m_settings->value(m_key).toString());
+
+ QVERIFY(op.undoOperation());
+ QCOMPARE(m_settings->value(m_key).toString(), m_oldValue);
+ m_settings->remove(m_key);
+ }
+
+ void testNonPersistentNonSystemOldValue()
+ {
+ m_settings->setValue(m_key, m_oldValue);
+ Environment::instance().setTemporaryValue(m_key, m_oldValue);
+ EnvironmentVariableOperation op(nullptr);
+ op.setArguments( QStringList() << m_key
+ << m_value
+ << QLatin1String("false")
+ << QLatin1String("false"));
+ const bool ok = op.performOperation();
+
+ QVERIFY2(ok, qPrintable(op.errorString()));
+
+ QVERIFY(op.undoOperation());
+ QCOMPARE(m_oldValue, Environment::instance().value(m_key));
+ }
+
+ void testEnvVariableFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testEnvVariableFromSXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+
+private:
+ QSettings *m_settings;
+ QString m_key;
+ QString m_value;
+ QString m_oldValue;
+};
+
+QTEST_MAIN(tst_environmentvariableoperation)
+
+#include "tst_environmentvariableoperation.moc"
+
diff --git a/tests/auto/installer/extractarchiveoperationtest/data.qrc b/tests/auto/installer/extractarchiveoperationtest/data.qrc
index d6453a9b3..87f648568 100644
--- a/tests/auto/installer/extractarchiveoperationtest/data.qrc
+++ b/tests/auto/installer/extractarchiveoperationtest/data.qrc
@@ -2,5 +2,17 @@
<qresource prefix="/">
<file>data/valid.7z</file>
<file>data/invalid.7z</file>
+ <file>data/subdirs.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ <file>data/xmloperationrepository/A/1.0.0content.7z</file>
+ <file>data/xmloperationrepository/A/1.0.0content1.tar.gz</file>
+ <file>data/xmloperationrepository/A/1.0.0content2.tar.bz2</file>
+ <file>data/xmloperationrepository/A/1.0.0content3.tar.xz</file>
+ <file>data/xmloperationrepository/A/1.0.0content4.zip</file>
+ <file>data/xmloperationrepository/A/1.0.0anothercontent.7z</file>
+ <file>data/xmloperationrepository/A/1.0.0default.7z</file>
+ <file>data/installerbaserepository/Updates.xml</file>
+ <file>data/installerbaserepository/A/1.0.0content.7z</file>
+ <file>data/installerbaserepository/A/1.0.0installerbase.7z</file>
</qresource>
</RCC>
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0content.7z b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0content.7z
new file mode 100644
index 000000000..585f58296
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0installerbase.7z b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0installerbase.7z
new file mode 100644
index 000000000..c3b6aec9c
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/A/1.0.0installerbase.7z
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/Updates.xml b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/Updates.xml
new file mode 100644
index 000000000..887300c97
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/installerbaserepository/Updates.xml
@@ -0,0 +1,13 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>InstallerBase</DisplayName>
+ <Description>Example component InstallerBase</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <DownloadableArchives>installerbase.7z,content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z b/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z
new file mode 100644
index 000000000..7f93fe106
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/subdirs.7z
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0anothercontent.7z b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0anothercontent.7z
new file mode 100644
index 000000000..949b50689
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0anothercontent.7z
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content.7z b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content.7z
new file mode 100644
index 000000000..585f58296
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content1.tar.gz b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content1.tar.gz
new file mode 100644
index 000000000..3e494db34
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content1.tar.gz
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content2.tar.bz2 b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content2.tar.bz2
new file mode 100644
index 000000000..12cbef8a1
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content2.tar.bz2
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content3.tar.xz b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content3.tar.xz
new file mode 100644
index 000000000..bfa825493
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content3.tar.xz
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content4.zip b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content4.zip
new file mode 100644
index 000000000..866bfa589
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0content4.zip
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0default.7z b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0default.7z
new file mode 100644
index 000000000..1c0c5ccfb
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/A/1.0.0default.7z
Binary files differ
diff --git a/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/Updates.xml b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..73a093725
--- /dev/null
+++ b/tests/auto/installer/extractarchiveoperationtest/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,42 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <DownloadableArchives>content.7z,anothercontent.7z,content1.tar.gz,content2.tar.bz2,content3.tar.xz,content4.zip,default.7z</DownloadableArchives>
+ <Operations>
+ <Operation name="Extract">
+ <Argument>@TargetDir@/FolderForContent</Argument>
+ <Argument>content.7z</Argument>
+ </Operation>
+ <Operation name="Extract">
+ <Argument>@TargetDir@/FolderForAnotherContent</Argument>
+ <Argument>anothercontent.7z</Argument>
+ </Operation>
+ <Operation name="Extract">
+ <Argument>@TargetDir@/FolderForTarGzContent</Argument>
+ <Argument>content1.tar.gz</Argument>
+ </Operation>
+ <Operation name="Extract">
+ <Argument>@TargetDir@/FolderForTarBz2Content</Argument>
+ <Argument>content2.tar.bz2</Argument>
+ </Operation>
+ <Operation name="Extract">
+ <Argument>@TargetDir@/FolderForTarXzContent</Argument>
+ <Argument>content3.tar.xz</Argument>
+ </Operation>
+ <Operation name="Extract">
+ <Argument>@TargetDir@/FolderForZipContent</Argument>
+ <Argument>content4.zip</Argument>
+ </Operation>
+ <Operation name="Extract">
+ <Argument>@TargetDir@/FolderForDefault</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/extractarchiveoperationtest/extractarchiveoperationtest.pro b/tests/auto/installer/extractarchiveoperationtest/extractarchiveoperationtest.pro
index fb53c9a8a..e0da85b0a 100644
--- a/tests/auto/installer/extractarchiveoperationtest/extractarchiveoperationtest.pro
+++ b/tests/auto/installer/extractarchiveoperationtest/extractarchiveoperationtest.pro
@@ -3,5 +3,6 @@ include(../../qttest.pri)
QT -= gui
QT += testlib
-RESOURCES += data.qrc
+RESOURCES += data.qrc \
+ ../shared/config.qrc
SOURCES = tst_extractarchiveoperationtest.cpp
diff --git a/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp b/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp
index a5f38e0ea..a8a65e983 100644
--- a/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp
+++ b/tests/auto/installer/extractarchiveoperationtest/tst_extractarchiveoperationtest.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -26,6 +26,9 @@
**
**************************************************************************/
+#include "../shared/packagemanager.h"
+
+#include "concurrentoperationrunner.h"
#include "init.h"
#include "extractarchiveoperation.h"
@@ -40,6 +43,8 @@ class tst_extractarchiveoperationtest : public QObject
{
Q_OBJECT
+private:
+
private slots:
void initTestCase()
{
@@ -80,9 +85,133 @@ private slots:
QVERIFY(op.undoOperation());
QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError);
- QCOMPARE(op.errorString(), QString("Error while extracting archive \":///data/invalid.7z\": "
- "Cannot open archive \":///data/invalid.7z\"."));
}
+
+ void testConcurrentExtractWithCompetingData()
+ {
+ // Suppress warnings about already deleted installerResources file
+ qInstallMessageHandler(silentTestMessageHandler);
+
+ const QString testDirectory = generateTemporaryFileName()
+ + "/subdir1/subdir2/subdir3/subdir4/subdir5/";
+
+ QStringList created7zList;
+
+ OperationList operations;
+ for (int i = 0; i < 100; ++i) {
+ ExtractArchiveOperation *op = new ExtractArchiveOperation(nullptr);
+ // We add the same data multiple times, and extract to same directory.
+ // Can't open the same archive multiple times however so it needs to
+ // be copied to unique files.
+ const QString new7zPath = generateTemporaryFileName() + ".7z";
+ QFile old7z(":///data/subdirs.7z");
+ QVERIFY(old7z.copy(new7zPath));
+
+ op->setArguments(QStringList() << new7zPath << testDirectory);
+ operations.append(op);
+ }
+ ConcurrentOperationRunner runner(&operations, Operation::Backup);
+
+ const QHash<Operation *, bool> backupResults = runner.run();
+ const OperationList backupOperations = backupResults.keys();
+
+ for (auto *operation : backupOperations)
+ QVERIFY2((backupResults.value(operation) && operation->error() == Operation::NoError),
+ operation->errorString().toLatin1());
+
+ runner.setType(Operation::Perform);
+ const QHash<Operation *, bool> results = runner.run();
+ const OperationList performedOperations = results.keys();
+
+ for (auto *operation : performedOperations)
+ QVERIFY2((results.value(operation) && operation->error() == Operation::NoError),
+ operation->errorString().toLatin1());
+
+ for (auto *operation : operations)
+ QVERIFY(operation->undoOperation());
+
+ qDeleteAll(operations);
+
+ for (const QString &archive : created7zList)
+ QFile::remove(archive);
+
+ QDir().rmdir(testDirectory);
+ }
+
+ void testExtractArchiveFromXML()
+ {
+ m_testDirectory = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_testDirectory));
+ QVERIFY(QDir(m_testDirectory).exists());
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_testDirectory, ":///data/xmloperationrepository"));
+ core->installDefaultComponentsSilently();
+
+ QFile extractedFile(m_testDirectory + QDir::separator() + "FolderForContent/content.txt");
+ QVERIFY(extractedFile.exists());
+#ifdef IFW_LIBARCHIVE
+ extractedFile.setFileName(m_testDirectory + QDir::separator() + "FolderForTarGzContent/content.txt");
+ QVERIFY(extractedFile.exists());
+
+ extractedFile.setFileName(m_testDirectory + QDir::separator() + "FolderForTarBz2Content/content.txt");
+ QVERIFY(extractedFile.exists());
+
+ extractedFile.setFileName(m_testDirectory + QDir::separator() + "FolderForTarXzContent/content.txt");
+ QVERIFY(extractedFile.exists());
+
+ extractedFile.setFileName(m_testDirectory + QDir::separator() + "FolderForZipContent/content.txt");
+ QVERIFY(extractedFile.exists());
+#endif
+ extractedFile.setFileName(m_testDirectory + QDir::separator() + "FolderForAnotherContent/anothercontent.txt");
+ QVERIFY(extractedFile.exists());
+
+ extractedFile.setFileName(m_testDirectory + QDir::separator() + "FolderForDefault/default.txt");
+ QVERIFY(extractedFile.exists());
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QDir dir(m_testDirectory);
+ QVERIFY(dir.removeRecursively());
+ }
+
+ void testInstallerBaseBinaryExtraction()
+ {
+ m_testDirectory = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_testDirectory));
+ QVERIFY(QDir(m_testDirectory).exists());
+
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_testDirectory, ":///data/installerbaserepository"));
+ core->setInstallerBaseBinary(m_testDirectory + QDir::separator() + "testInstallerBase.txt");
+ core->installDefaultComponentsSilently();
+
+ QFile contentResourceFile(m_testDirectory + QDir::separator() + "installerResources" + QDir::separator() + "A" + QDir::separator() + "1.0.0content.txt");
+ QVERIFY2(contentResourceFile.open(QIODevice::ReadOnly | QIODevice::Text), "Could not open content resource file for reading.");
+ QTextStream fileStream(&contentResourceFile);
+ QString line = fileStream.readLine();
+ QVERIFY2(!line.isEmpty(), "Content not written to resource file.");
+ contentResourceFile.close();
+
+ QFile installerBaseResourceFile(m_testDirectory + QDir::separator() + "installerResources" + QDir::separator() + "A" + QDir::separator() + "1.0.0installerbase.txt");
+ QVERIFY2(installerBaseResourceFile.open(QIODevice::ReadOnly | QIODevice::Text), "Could not open installerbase resource file for reading.");
+ QTextStream fileStream2(&installerBaseResourceFile);
+ line = installerBaseResourceFile.readLine();
+ QVERIFY2(line.isEmpty(), "Installerbase falsly written to resource file.");
+ installerBaseResourceFile.close();
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+
+ QCOMPARE(PackageManagerCore::Success, core->uninstallComponentsSilently(QStringList() << "A"));
+ QDir dir(m_testDirectory);
+ QVERIFY(dir.removeRecursively());
+ }
+
+private:
+ QString m_testDirectory;
};
QTEST_MAIN(tst_extractarchiveoperationtest)
diff --git a/tests/auto/installer/factory/tst_factory.cpp b/tests/auto/installer/factory/tst_factory.cpp
index a693a2ce6..4b6932c09 100644
--- a/tests/auto/installer/factory/tst_factory.cpp
+++ b/tests/auto/installer/factory/tst_factory.cpp
@@ -1,32 +1,26 @@
/**************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $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 http://qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
@@ -77,7 +71,7 @@ public:
: Food(amount)
, m_expireDate(expireDate)
{ qDebug().nospace().noquote() << "Constructor."; }
- QDate expireDate() const {
+ QDate expireDate() const override {
return m_expireDate;
}
private:
@@ -87,7 +81,7 @@ private:
class Butter : public Food
{
public:
- QDate expireDate() const {
+ QDate expireDate() const override {
return m_expireDate;
}
static Food *create(int amount, const QDate expireDate) {
@@ -112,7 +106,7 @@ public:
: Food(amount)
, m_expireDate(expireDate)
{ qDebug().nospace().noquote() << "Constructor."; }
- QDate expireDate() const {
+ QDate expireDate() const override {
return m_expireDate;
}
diff --git a/tests/auto/installer/fileutils/fileutils.pro b/tests/auto/installer/fileutils/fileutils.pro
new file mode 100644
index 000000000..eee7ec537
--- /dev/null
+++ b/tests/auto/installer/fileutils/fileutils.pro
@@ -0,0 +1,6 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_fileutils.cpp
diff --git a/tests/auto/installer/fileutils/tst_fileutils.cpp b/tests/auto/installer/fileutils/tst_fileutils.cpp
new file mode 100644
index 000000000..5472e1403
--- /dev/null
+++ b/tests/auto/installer/fileutils/tst_fileutils.cpp
@@ -0,0 +1,135 @@
+/**************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include <qinstallerglobal.h>
+#include <fileutils.h>
+
+#include <QObject>
+#include <QTest>
+#include <QFile>
+#include <QDir>
+
+using namespace QInstaller;
+
+class tst_fileutils : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testSetDefaultFilePermissions()
+ {
+#if defined(Q_OS_WIN)
+ QString fileName = QInstaller::generateTemporaryFileName();
+ QFile testFile(fileName);
+
+ QVERIFY(testFile.open(QIODevice::ReadWrite));
+ QVERIFY(testFile.exists());
+ testFile.close();
+
+ // Set permissions containing none of the Write* flags, this will cause
+ // the read-only flag to be set for the file
+ QVERIFY(testFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::ReadUser
+ | QFileDevice::ReadGroup | QFileDevice::ReadOther));
+
+ // Verify that the file cannot be opened for both reading and writing, i.e.
+ // it should be read-only.
+ QVERIFY(!testFile.open(QIODevice::ReadWrite));
+
+ // Now try to remove the read-only flag
+ QVERIFY(setDefaultFilePermissions(&testFile, DefaultFilePermissions::NonExecutable));
+
+ // Verify that the file can now be opened for both reading and writing
+ QVERIFY(testFile.open(QIODevice::ReadWrite));
+ testFile.close();
+
+ QVERIFY(testFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::ReadUser
+ | QFileDevice::ReadGroup | QFileDevice::ReadOther));
+
+ // Check that the behavior is same with 'Executable' argument
+ QVERIFY(setDefaultFilePermissions(&testFile, DefaultFilePermissions::Executable));
+
+ QVERIFY(testFile.open(QIODevice::ReadWrite));
+ testFile.close();
+
+ QVERIFY(testFile.remove());
+#elif defined(Q_OS_UNIX)
+ // Need to include the "user" flags here as they will be returned
+ // by QFile::permissions(). Same as owner permissions of the file.
+ QFlags<QFileDevice::Permission> permissions(QFileDevice::ReadOwner
+ | QFileDevice::WriteOwner | QFileDevice::ReadUser | QFileDevice::WriteUser
+ | QFileDevice::ReadGroup | QFileDevice::ReadOther);
+
+ QFlags<QFileDevice::Permission> exePermissions(permissions | QFileDevice::ExeOwner
+ | QFileDevice::ExeUser | QFileDevice::ExeGroup | QFileDevice::ExeOther);
+
+ QString fileName = QInstaller::generateTemporaryFileName();
+ QFile testFile(fileName);
+
+ const QString message = "Target \"%1\" does not exists.";
+
+ // Test non-existing file
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message.arg(fileName)));
+ QVERIFY(!setDefaultFilePermissions(fileName, DefaultFilePermissions::NonExecutable));
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(message.arg(testFile.fileName())));
+ QVERIFY(!setDefaultFilePermissions(&testFile, DefaultFilePermissions::NonExecutable));
+
+ QVERIFY(testFile.open(QIODevice::ReadWrite));
+ QVERIFY(testFile.exists());
+ testFile.close();
+
+ // Test with file name
+ QVERIFY(setDefaultFilePermissions(fileName, DefaultFilePermissions::NonExecutable));
+ QCOMPARE(QFile().permissions(fileName), permissions);
+
+ QVERIFY(setDefaultFilePermissions(fileName, DefaultFilePermissions::Executable));
+ QCOMPARE(QFile().permissions(fileName), exePermissions);
+
+ // Test with QFile object
+ QVERIFY(setDefaultFilePermissions(&testFile, DefaultFilePermissions::NonExecutable));
+ QCOMPARE(QFile().permissions(fileName), permissions);
+
+ QVERIFY(setDefaultFilePermissions(&testFile, DefaultFilePermissions::Executable));
+ QCOMPARE(QFile().permissions(fileName), exePermissions);
+
+ // Test with directory path
+ QString testDir = QDir().tempPath() + QLatin1String("/testDir");
+ QVERIFY(QDir().mkdir(testDir));
+
+ QVERIFY(setDefaultFilePermissions(testDir, DefaultFilePermissions::Executable));
+ QCOMPARE(QFile().permissions(testDir), exePermissions);
+
+ QVERIFY(QDir().rmdir(testDir));
+ QVERIFY(testFile.remove());
+#endif
+ }
+};
+
+QTEST_MAIN(tst_fileutils)
+
+#include "tst_fileutils.moc"
diff --git a/tests/auto/installer/globalsettingsoperation/globalsettingsoperation.pro b/tests/auto/installer/globalsettingsoperation/globalsettingsoperation.pro
new file mode 100644
index 000000000..c9e959cac
--- /dev/null
+++ b/tests/auto/installer/globalsettingsoperation/globalsettingsoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_globalsettingsoperation.cpp
+
+RESOURCES += \
+ ../shared/config.qrc
+
diff --git a/tests/auto/installer/globalsettingsoperation/tst_globalsettingsoperation.cpp b/tests/auto/installer/globalsettingsoperation/tst_globalsettingsoperation.cpp
new file mode 100644
index 000000000..009673f24
--- /dev/null
+++ b/tests/auto/installer/globalsettingsoperation/tst_globalsettingsoperation.cpp
@@ -0,0 +1,95 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+
+#include <globalsettingsoperation.h>
+#include <environment.h>
+#include <packagemanagercore.h>
+
+#include <QSettings>
+#include <QTest>
+
+using namespace QInstaller;
+using namespace KDUpdater;
+
+class tst_globalsettingsoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void cleanSettings()
+ {
+ QSettings testSettings("QtProject", "QtProject.QtIfwTest");
+ testSettings.setValue("QtIfwTestKey", "");
+ }
+
+
+private slots:
+ void initTestCase()
+ {
+ cleanSettings();
+ }
+
+ void cleanupTestCase()
+ {
+ cleanSettings();
+ }
+
+ void setGlobalSettingsValue()
+ {
+ GlobalSettingsOperation settingsOperation(nullptr);
+ settingsOperation.setArguments(QStringList() << "QtProject" << "QtProject.QtIfwTest" << "QtIfwTestKey" << "QtIfwTestValue");
+ settingsOperation.backup();
+ QVERIFY2(settingsOperation.performOperation(), settingsOperation.errorString().toLatin1());
+
+ QSettings testSettings("QtProject", "QtProject.QtIfwTest");
+ QCOMPARE("QtIfwTestValue", testSettings.value("QtIfwTestKey"));
+ QVERIFY2(settingsOperation.undoOperation(), settingsOperation.errorString().toLatin1());
+ QCOMPARE("", testSettings.value("QtIfwTestKey"));
+ }
+
+ void setGlobalSettingsValueNoUndo()
+ {
+
+ GlobalSettingsOperation settingsOperation(nullptr);
+ settingsOperation.setArguments(QStringList() << "QtProject" << "QtProject.QtIfwTest" << "QtIfwTestKey" << "QtIfwTestValue" << "UNDOOPERATION" << "");
+ settingsOperation.backup();
+ QVERIFY2(settingsOperation.performOperation(), settingsOperation.errorString().toLatin1());
+
+ QSettings testSettings("QtProject", "QtProject.QtIfwTest");
+ QCOMPARE("QtIfwTestValue", testSettings.value("QtIfwTestKey"));
+ QVERIFY2(settingsOperation.undoOperation(), settingsOperation.errorString().toLatin1());
+ QCOMPARE("QtIfwTestValue", testSettings.value("QtIfwTestKey"));
+ }
+};
+
+QTEST_MAIN(tst_globalsettingsoperation)
+
+#include "tst_globalsettingsoperation.moc"
+
diff --git a/tests/auto/installer/installer.pro b/tests/auto/installer/installer.pro
index 7081a6316..b2eb57790 100644
--- a/tests/auto/installer/installer.pro
+++ b/tests/auto/installer/installer.pro
@@ -1,6 +1,7 @@
TEMPLATE = subdirs
SUBDIRS += \
+ archivefactory \
settings \
repository \
compareversion\
@@ -9,11 +10,12 @@ SUBDIRS += \
fakestopprocessforupdateoperation \
messageboxhandler \
extractarchiveoperationtest \
- lib7zfacade \
+ fileutils \
unicodeexecutable \
scriptengine \
consumeoutputoperationtest \
mkdiroperationtest \
+ rmdiroperationtest \
copyoperationtest \
solver \
binaryformat \
@@ -22,9 +24,47 @@ SUBDIRS += \
task \
clientserver \
factory \
- replaceoperation
+ replaceoperation \
+ brokeninstaller \
+ commandlineinstall \
+ linereplaceoperation \
+ metadatajob \
+ appendfileoperation \
+ prependfileoperation \
+ simplemovefileoperation \
+ deleteoperation \
+ copydirectoryoperation \
+ commandlineupdate \
+ moveoperation \
+ environmentvariableoperation \
+ licenseagreement \
+ globalsettingsoperation \
+ elevatedexecuteoperation \
+ treename \
+ createoffline \
+ contentshaupdate \
+ componentreplace \
+ metadatacache \
+ contentsha1check \
+ componentalias
+
+CONFIG(libarchive) {
+ SUBDIRS += libarchivearchive
+}
+
+CONFIG(lzmasdk) {
+ SUBDIRS += lib7zarchive
+}
win32 {
- SUBDIRS += registerfiletypeoperation
+ SUBDIRS += registerfiletypeoperation \
+ createshortcutoperation
}
+
+linux-g++* {
+ SUBDIRS += \
+ createdesktopentryoperation \
+ installiconsoperation
+}
+
scriptengine.depends += unicodeexecutable
diff --git a/tests/auto/installer/installiconsoperation/data/repository/A/1.0.2-1content.7z b/tests/auto/installer/installiconsoperation/data/repository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..9d58b172e
--- /dev/null
+++ b/tests/auto/installer/installiconsoperation/data/repository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/installiconsoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/installiconsoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..74e201fc3
--- /dev/null
+++ b/tests/auto/installer/installiconsoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/installiconsoperation/data/repository/Updates.xml b/tests/auto/installer/installiconsoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..201e23c2d
--- /dev/null
+++ b/tests/auto/installer/installiconsoperation/data/repository/Updates.xml
@@ -0,0 +1,16 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>13c9e7e67c26e7fbf49cc30887d87140b65e11b5</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/installiconsoperation/data/xmloperationrepository/A/1.0.2-1content.7z b/tests/auto/installer/installiconsoperation/data/xmloperationrepository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..9d58b172e
--- /dev/null
+++ b/tests/auto/installer/installiconsoperation/data/xmloperationrepository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/installiconsoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/installiconsoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..5977964f2
--- /dev/null
+++ b/tests/auto/installer/installiconsoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,18 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Operations>
+ <Operation name="InstallIcons">
+ <Argument>@TargetDir@/icons</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/installiconsoperation/installiconsoperation.pro b/tests/auto/installer/installiconsoperation/installiconsoperation.pro
new file mode 100644
index 000000000..be4cd0b3d
--- /dev/null
+++ b/tests/auto/installer/installiconsoperation/installiconsoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_installiconsoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/installiconsoperation/settings.qrc b/tests/auto/installer/installiconsoperation/settings.qrc
new file mode 100644
index 000000000..094bd449b
--- /dev/null
+++ b/tests/auto/installer/installiconsoperation/settings.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1content.7z</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ <file>data/xmloperationrepository/A/1.0.2-1content.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/installiconsoperation/tst_installiconsoperation.cpp b/tests/auto/installer/installiconsoperation/tst_installiconsoperation.cpp
new file mode 100644
index 000000000..3dc981652
--- /dev/null
+++ b/tests/auto/installer/installiconsoperation/tst_installiconsoperation.cpp
@@ -0,0 +1,235 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <installiconsoperation.h>
+
+#include <packagemanagercore.h>
+#include <component.h>
+
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_installiconsoperation : public QObject
+{
+ Q_OBJECT
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (installDir, repository));
+ core->installDefaultComponentsSilently();
+
+ InstallIconsOperation *installIconsOp = nullptr;
+ OperationList operations = core->componentByName("A")->operations();
+ foreach (Operation *op, operations) {
+ if (op->name() == QLatin1String("InstallIcons"))
+ installIconsOp = dynamic_cast<InstallIconsOperation *>(op);
+ }
+ QVERIFY(installIconsOp);
+
+ // As the original directory containing icons will be deleted by the operation,
+ // we will use a copy with the exact same contents.
+ QFileInfo fakeSourceInfo(installDir + "/icons_copy/test");
+ QMap<QString, QByteArray> fakeSourceMap;
+ VerifyInstaller::addToFileMap(QDir(fakeSourceInfo.absoluteFilePath()), fakeSourceInfo, fakeSourceMap);
+
+ QFileInfo destinationInfo(installIconsOp->value("directory").toString() + "/test");
+ QMap<QString, QByteArray> destinationMap;
+ VerifyInstaller::addToFileMap(QDir(destinationInfo.absoluteFilePath()), destinationInfo, destinationMap);
+
+ QVERIFY(fakeSourceMap == destinationMap);
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QVERIFY(!destinationInfo.exists());
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_testIconSourcePath = qApp->applicationDirPath() + "/icons";
+ m_testIconSubdirectoryPath = m_testIconSourcePath + "/test";
+
+ m_testIconFilePaths.append(m_testIconSubdirectoryPath
+ + QDir::separator() + "vendor-icon1.png");
+ m_testIconFilePaths.append(m_testIconSubdirectoryPath
+ + QDir::separator() + "vendor-icon2.png");
+ m_testIconFilePaths.append(m_testIconSubdirectoryPath
+ + QDir::separator() + "vendor-icon3.png");
+ }
+
+ void testMissingArguments()
+ {
+ InstallIconsOperation op(nullptr);
+
+ op.backup();
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in InstallIcons: "
+ "0 arguments given, 1 or 2 arguments expected "
+ "in the form: <source path> [vendor prefix]."));
+
+ op.setArguments(QStringList() << "");
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid Argument: source directory must not be empty."));
+ }
+
+ void testInstallIconsFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testInstallIconsFromXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+
+ void testInstallIconsWithUndo()
+ {
+ QDir testIconDir(m_testIconSourcePath);
+ QVERIFY(testIconDir.mkpath(m_testIconSubdirectoryPath));
+
+ // Populate source directory
+ foreach (const QString &filePath, m_testIconFilePaths) {
+ QFile file(filePath);
+ QVERIFY(file.open(QFileDevice::ReadWrite));
+ file.close();
+ }
+
+ PackageManagerCore *core = new PackageManagerCore();
+ InstallIconsOperation op(core);
+ op.setArguments(QStringList() << m_testIconSourcePath);
+
+ QFileInfo sourceInfo(m_testIconSubdirectoryPath);
+ QMap<QString, QByteArray> sourceMap;
+ VerifyInstaller::addToFileMap(QDir(sourceInfo.absoluteFilePath()), sourceInfo, sourceMap);
+
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo().exists(m_testIconSourcePath));
+
+ QFileInfo destinationInfo(op.value("directory").toString() + "/test");
+ QMap<QString, QByteArray> destinationMap;
+ VerifyInstaller::addToFileMap(QDir(destinationInfo.absoluteFilePath()), destinationInfo, destinationMap);
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo().exists(op.value("directory").toString() + "/test"));
+ QVERIFY(QFileInfo().exists(m_testIconSourcePath));
+
+ QVERIFY(sourceMap == destinationMap);
+ QVERIFY(testIconDir.removeRecursively());
+
+ core->deleteLater();
+ }
+
+ void testChangeVendorPrefix()
+ {
+ QDir testIconDir(m_testIconSourcePath);
+ QVERIFY(testIconDir.mkpath(m_testIconSubdirectoryPath));
+
+ QFile file(m_testIconFilePaths.first());
+ QVERIFY(file.open(QFileDevice::ReadWrite));
+ file.close();
+
+ PackageManagerCore *core = new PackageManagerCore();
+ InstallIconsOperation op(core);
+ op.setArguments(QStringList() << m_testIconSourcePath << "testVendor");
+
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo().exists(m_testIconSourcePath));
+ QVERIFY(QFileInfo().exists(op.value("directory").toString() + "/test/testVendor-icon1.png"));
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo().exists(op.value("directory").toString() + "/test"));
+ QVERIFY(QFileInfo().exists(m_testIconSourcePath));
+
+ QVERIFY(testIconDir.removeRecursively());
+
+ core->deleteLater();
+ }
+
+ void testValidTargetDirectory()
+ {
+ QDir testIconDir(m_testIconSourcePath);
+ QVERIFY(testIconDir.mkpath(m_testIconSubdirectoryPath));
+
+ PackageManagerCore *core = new PackageManagerCore();
+ InstallIconsOperation op(core);
+ op.setArguments(QStringList() << m_testIconSourcePath);
+
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo().exists(m_testIconSourcePath));
+
+ QString targetIconsDirectory = op.value("directory").toString();
+ QVERIFY(QFileInfo(targetIconsDirectory).exists());
+ QStringList directories = QString::fromLocal8Bit(qgetenv("XDG_DATA_HOME"))
+ .split(QLatin1Char(':'), Qt::SkipEmptyParts);
+ // Default path if XDG_DATA_HOME is not set
+ directories.append(QDir::home().absoluteFilePath(QLatin1String(".local/share")));
+ // Default path if run as root
+ directories.append(QLatin1String("/usr/local/share"));
+ bool validPath = false;
+ foreach (const QString &dir, directories) {
+ // Icon directory should be one of the expected locations
+ if (targetIconsDirectory == QDir(dir).absoluteFilePath("icons")) {
+ validPath = true;
+ break;
+ }
+ }
+ QVERIFY(validPath);
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo().exists(op.value("directory").toString() + "/test"));
+
+ QVERIFY(testIconDir.removeRecursively());
+ core->deleteLater();
+ }
+
+private:
+ QString m_testIconSourcePath;
+ QString m_testIconSubdirectoryPath;
+ QStringList m_testIconFilePaths;
+};
+
+QTEST_MAIN(tst_installiconsoperation)
+
+#include "tst_installiconsoperation.moc"
diff --git a/tests/auto/installer/lib7zfacade/data.qrc b/tests/auto/installer/lib7zarchive/data.qrc
index d6453a9b3..d6453a9b3 100644
--- a/tests/auto/installer/lib7zfacade/data.qrc
+++ b/tests/auto/installer/lib7zarchive/data.qrc
diff --git a/tests/auto/installer/lib7zfacade/data/invalid.7z b/tests/auto/installer/lib7zarchive/data/invalid.7z
index bcf81250e..bcf81250e 100644
--- a/tests/auto/installer/lib7zfacade/data/invalid.7z
+++ b/tests/auto/installer/lib7zarchive/data/invalid.7z
Binary files differ
diff --git a/tests/auto/installer/lib7zfacade/data/valid.7z b/tests/auto/installer/lib7zarchive/data/valid.7z
index e583bdf99..e583bdf99 100644
--- a/tests/auto/installer/lib7zfacade/data/valid.7z
+++ b/tests/auto/installer/lib7zarchive/data/valid.7z
Binary files differ
diff --git a/tests/auto/installer/lib7zfacade/lib7zfacade.pro b/tests/auto/installer/lib7zarchive/lib7zarchive.pro
index 034cf1eed..aabf724b6 100644
--- a/tests/auto/installer/lib7zfacade/lib7zfacade.pro
+++ b/tests/auto/installer/lib7zarchive/lib7zarchive.pro
@@ -4,4 +4,4 @@ QT -= gui
QT += testlib
RESOURCES += data.qrc
-SOURCES = tst_lib7zfacade.cpp
+SOURCES = tst_lib7zarchive.cpp
diff --git a/tests/auto/installer/lib7zarchive/tst_lib7zarchive.cpp b/tests/auto/installer/lib7zarchive/tst_lib7zarchive.cpp
new file mode 100644
index 000000000..a94b0f818
--- /dev/null
+++ b/tests/auto/installer/lib7zarchive/tst_lib7zarchive.cpp
@@ -0,0 +1,149 @@
+/**************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include <lib7z_facade.h>
+#include <lib7zarchive.h>
+#include <fileutils.h>
+
+#include <QDir>
+#include <QObject>
+#include <QTemporaryFile>
+#include <QTest>
+
+using namespace QInstaller;
+
+class tst_lib7zarchive : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase()
+ {
+ Lib7z::initSevenZ();
+
+ m_file.path = "valid";
+ m_file.compressedSize = 836;
+ m_file.uncompressedSize = 5242880;
+ m_file.isDirectory = false;
+ m_file.archiveIndex = QPoint(0, 0);
+ m_file.utcTime = QDateTime(QDate::fromJulianDay(2456413), QTime(10, 50, 42), Qt::UTC);
+ }
+
+ void testIsSupportedArchive()
+ {
+ Lib7zArchive archive(":///data/valid.7z");
+ QVERIFY(archive.open(QIODevice::ReadOnly));
+ QCOMPARE(archive.isSupported(), true);
+ archive.close();
+
+ archive.setFilename(":///data/invalid.7z");
+ QVERIFY(archive.open(QIODevice::ReadOnly));
+ QCOMPARE(archive.isSupported(), false);
+ }
+
+ void testListArchive()
+ {
+
+ Lib7zArchive archive(":///data/valid.7z");
+ QVERIFY(archive.open(QIODevice::ReadOnly));
+
+ QVector<ArchiveEntry> files = archive.list();
+ QCOMPARE(files.count(), 1);
+ QCOMPARE(files.first(), m_file);
+ archive.close();
+
+ archive.setFilename(":///data/invalid.7z");
+ QVERIFY(archive.open(QIODevice::ReadOnly));
+ files = archive.list();
+
+ QVERIFY(files.isEmpty());
+ QCOMPARE(archive.errorString(), QString("Cannot open archive \":///data/invalid.7z\"."));
+ }
+
+ void testCreateArchive()
+ {
+ QString path1 = tempSourceFile("Source File 1.");
+ QString path2 = tempSourceFile("Source File 2.");
+
+ QString filename = generateTemporaryFileName();
+ Lib7zArchive target(filename);
+ QVERIFY(target.open(QIODevice::ReadWrite));
+ QVERIFY(target.create(QStringList() << path1 << path2));
+ QCOMPARE(target.list().count(), 2);
+ target.close();
+ QVERIFY(QFile::remove(filename));
+
+
+ path1 = tempSourceFile(
+ "Source File 1.",
+ QDir::tempPath() + "/temp file with spaces.XXXXXX"
+ );
+ path2 = tempSourceFile(
+ "Source File 2.",
+ QDir::tempPath() + "/temp file with spaces.XXXXXX"
+ );
+
+ filename = QDir::tempPath() + "/target file with spaces.XXXXXX";
+ target.setFilename(filename);
+ QVERIFY(target.open(QIODevice::ReadWrite));
+ QVERIFY(target.create(QStringList() << path1 << path2));
+ QCOMPARE(target.list().count(), 2);
+ target.close();
+ QVERIFY(QFile::remove(filename));
+ }
+
+ void testExtractArchive()
+ {
+ Lib7zArchive source(":///data/valid.7z");
+ QVERIFY(source.open(QIODevice::ReadOnly));
+
+ QVERIFY(source.extract(QDir::tempPath()));
+ QCOMPARE(QFile::exists(QDir::tempPath() + QString("/valid")), true);
+ QVERIFY(QFile::remove(QDir::tempPath() + QString("/valid")));
+ }
+
+private:
+ QString tempSourceFile(const QByteArray &data, const QString &templateName = QString())
+ {
+ QTemporaryFile source;
+ if (!templateName.isEmpty()) {
+ source.setFileTemplate(templateName);
+ }
+ source.open();
+ source.write(data);
+ source.setAutoRemove(false);
+ return source.fileName();
+ }
+
+private:
+ ArchiveEntry m_file;
+};
+
+QTEST_MAIN(tst_lib7zarchive)
+
+#include "tst_lib7zarchive.moc"
diff --git a/tests/auto/installer/lib7zfacade/tst_lib7zfacade.cpp b/tests/auto/installer/lib7zfacade/tst_lib7zfacade.cpp
deleted file mode 100644
index ffc5b330a..000000000
--- a/tests/auto/installer/lib7zfacade/tst_lib7zfacade.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/**************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Installer Framework.
-**
-** $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$
-**
-**************************************************************************/
-
-#include <lib7z_create.h>
-#include <lib7z_extract.h>
-#include <lib7z_facade.h>
-#include <lib7z_list.h>
-
-#include <QDir>
-#include <QObject>
-#include <QTemporaryFile>
-#include <QTest>
-
-class tst_lib7zfacade : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase()
- {
- Lib7z::initSevenZ();
-
- m_file.path = "valid";
- m_file.permissions = 0;
- m_file.compressedSize = 836;
- m_file.uncompressedSize = 5242880;
- m_file.isDirectory = false;
- m_file.archiveIndex = QPoint(0, 0);
- m_file.utcTime = QDateTime(QDate::fromJulianDay(2456413), QTime(10, 50, 42), Qt::UTC);
- }
-
- void testIsSupportedArchive()
- {
- QCOMPARE(Lib7z::isSupportedArchive(":///data/valid.7z"), true);
- QCOMPARE(Lib7z::isSupportedArchive(":///data/invalid.7z"), false);
-
- try {
- QFile file(":///data/valid.7z");
- QVERIFY(file.open(QIODevice::ReadOnly));
- QCOMPARE(Lib7z::isSupportedArchive(&file), true);
- } catch (...) {
- QFAIL("Unexpected error during Lib7z::isSupportedArchive.");
- }
-
- try {
- QFile file(":///data/invalid.7z");
- QVERIFY(file.open(QIODevice::ReadOnly));
- QCOMPARE(Lib7z::isSupportedArchive(&file), false);
- } catch (...) {
- QFAIL("Unexpected error during Lib7z::isSupportedArchive.");
- }
- }
-
- void testListArchive()
- {
- try {
- QFile file(":///data/valid.7z");
- QVERIFY(file.open(QIODevice::ReadOnly));
-
- QVector<Lib7z::File> files = Lib7z::listArchive(&file);
- QCOMPARE(files.count(), 1);
- QCOMPARE(files.first(), m_file);
- } catch (...) {
- QFAIL("Unexpected error during list archive.");
- }
-
- try {
- QFile file(":///data/invalid.7z");
- QVERIFY(file.open(QIODevice::ReadOnly));
- QVector<Lib7z::File> files = Lib7z::listArchive(&file);
- } catch (const Lib7z::SevenZipException& e) {
- QCOMPARE(e.message(), QString("Cannot open archive \":///data/invalid.7z\"."));
- } catch (...) {
- QFAIL("Unexpected error during list archive.");
- }
- }
-
- void testCreateArchive()
- {
- try {
- const QString path = tempSourceFile("Source File 1.");
- const QString path2 = tempSourceFile("Source File 2.");
-
- QTemporaryFile target;
- QVERIFY(target.open());
- Lib7z::createArchive(&target, QStringList() << path << path2);
- QCOMPARE(Lib7z::listArchive(&target).count(), 2);
- } catch (const Lib7z::SevenZipException& e) {
- QFAIL(e.message().toUtf8());
- } catch (...) {
- QFAIL("Unexpected error during create archive.");
- }
-
- try {
- const QString path1 = tempSourceFile(
- "Source File 1.",
- QDir::tempPath() + "/temp file with spaces.XXXXXX"
- );
- const QString path2 = tempSourceFile(
- "Source File 2.",
- QDir::tempPath() + "/temp file with spaces.XXXXXX"
- );
-
- QTemporaryFile target(QDir::tempPath() + "/target file with spaces.XXXXXX");
- QVERIFY(target.open());
- Lib7z::createArchive(&target, QStringList() << path1 << path2);
- QCOMPARE(Lib7z::listArchive(&target).count(), 2);
- } catch (const Lib7z::SevenZipException& e) {
- QFAIL(e.message().toUtf8());
- } catch (...) {
- QFAIL("Unexpected error during create archive.");
- }
-
- }
-
- void testExtractArchive()
- {
- QFile source(":///data/valid.7z");
- QVERIFY(source.open(QIODevice::ReadOnly));
-
- try {
- Lib7z::extractArchive(&source, QDir::tempPath());
- QCOMPARE(QFile::exists(QDir::tempPath() + QString("/valid")), true);
- } catch (const Lib7z::SevenZipException& e) {
- QFAIL(e.message().toUtf8());
- } catch (...) {
- QFAIL("Unexpected error during extract archive.");
- }
- }
-
-private:
- QString tempSourceFile(const QByteArray &data, const QString &templateName = QString())
- {
- QTemporaryFile source;
- if (!templateName.isEmpty()) {
- source.setFileTemplate(templateName);
- }
- source.open();
- source.write(data);
- source.setAutoRemove(false);
- return source.fileName();
- }
-
-private:
- Lib7z::File m_file;
-};
-
-QTEST_MAIN(tst_lib7zfacade)
-
-#include "tst_lib7zfacade.moc"
diff --git a/tests/auto/installer/libarchivearchive/data.qrc b/tests/auto/installer/libarchivearchive/data.qrc
new file mode 100644
index 000000000..b3f2a1933
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/data.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/valid.zip</file>
+ <file>data/valid.tar.gz</file>
+ <file>data/valid.tar.bz2</file>
+ <file>data/valid.tar.xz</file>
+ <file>data/valid.7z</file>
+ <file>data/valid.qbsp</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/libarchivearchive/data/valid.7z b/tests/auto/installer/libarchivearchive/data/valid.7z
new file mode 100644
index 000000000..e583bdf99
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/data/valid.7z
Binary files differ
diff --git a/tests/auto/installer/libarchivearchive/data/valid.qbsp b/tests/auto/installer/libarchivearchive/data/valid.qbsp
new file mode 100644
index 000000000..e583bdf99
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/data/valid.qbsp
Binary files differ
diff --git a/tests/auto/installer/libarchivearchive/data/valid.tar.bz2 b/tests/auto/installer/libarchivearchive/data/valid.tar.bz2
new file mode 100644
index 000000000..1a79b4cd4
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/data/valid.tar.bz2
Binary files differ
diff --git a/tests/auto/installer/libarchivearchive/data/valid.tar.gz b/tests/auto/installer/libarchivearchive/data/valid.tar.gz
new file mode 100644
index 000000000..d574487d2
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/data/valid.tar.gz
Binary files differ
diff --git a/tests/auto/installer/libarchivearchive/data/valid.tar.xz b/tests/auto/installer/libarchivearchive/data/valid.tar.xz
new file mode 100644
index 000000000..4851a63b1
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/data/valid.tar.xz
Binary files differ
diff --git a/tests/auto/installer/libarchivearchive/data/valid.zip b/tests/auto/installer/libarchivearchive/data/valid.zip
new file mode 100644
index 000000000..d6923e016
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/data/valid.zip
Binary files differ
diff --git a/tests/auto/installer/libarchivearchive/libarchivearchive.pro b/tests/auto/installer/libarchivearchive/libarchivearchive.pro
new file mode 100644
index 000000000..ac4856ede
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/libarchivearchive.pro
@@ -0,0 +1,7 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+RESOURCES += data.qrc
+SOURCES = tst_libarchivearchive.cpp
diff --git a/tests/auto/installer/libarchivearchive/tst_libarchivearchive.cpp b/tests/auto/installer/libarchivearchive/tst_libarchivearchive.cpp
new file mode 100644
index 000000000..ab7030e2f
--- /dev/null
+++ b/tests/auto/installer/libarchivearchive/tst_libarchivearchive.cpp
@@ -0,0 +1,338 @@
+/**************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/verifyinstaller.h"
+
+#include <libarchivearchive.h>
+#include <fileutils.h>
+
+#include <QDir>
+#include <QObject>
+#include <QTemporaryFile>
+#include <QTest>
+
+using namespace QInstaller;
+
+class tst_libarchivearchive : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase()
+ {
+ m_file.path = "valid";
+ m_file.permissions_mode = 0666;
+ m_file.compressedSize = 0; // unused
+ m_file.uncompressedSize = 5242880;
+ m_file.isDirectory = false;
+ m_file.archiveIndex = QPoint(0, 0);
+ m_file.utcTime = QDateTime(QDate::fromJulianDay(2456413), QTime(10, 50, 42), Qt::UTC);
+ }
+
+ void testIsSupportedArchive_data()
+ {
+ archiveFilenamesTestData();
+ }
+
+ void testIsSupportedArchive()
+ {
+ QFETCH(QString, filename);
+
+ LibArchiveArchive archive(filename);
+ QVERIFY(archive.open(QIODevice::ReadOnly));
+ QCOMPARE(archive.isSupported(), true);
+ }
+
+ void testListArchive_data()
+ {
+ archiveFilenamesTestData();
+ }
+
+ void testListArchive()
+ {
+ QFETCH(QString, filename);
+
+ LibArchiveArchive archive(filename);
+ QVERIFY(archive.open(QIODevice::ReadOnly));
+
+ QVector<ArchiveEntry> files = archive.list();
+ QCOMPARE(files.count(), 1);
+ QCOMPARE(files.first(), m_file);
+ }
+
+ void testCreateArchive_data()
+ {
+ archiveSuffixesTestData();
+ }
+
+ void testCreateArchive()
+ {
+ QFETCH(QString, suffix);
+
+ const QString path1 = tempSourceFile("Source File 1.");
+ const QString path2 = tempSourceFile("Source File 2.");
+
+ const QString filename = generateTemporaryFileName() + suffix;
+ LibArchiveArchive target(filename);
+ QVERIFY(target.open(QIODevice::WriteOnly));
+ QVERIFY(target.create(QStringList() << path1 << path2));
+ target.close();
+ QVERIFY(target.open(QIODevice::ReadOnly));
+ QCOMPARE(target.list().count(), 2);
+ target.close();
+ QVERIFY(QFile(filename).remove());
+ }
+
+ void testCreateArchiveWithGlobPattern_data()
+ {
+ archiveSuffixesTestData();
+ }
+
+ void testCreateArchiveWithGlobPattern()
+ {
+ QFETCH(QString, suffix);
+
+ const QString baseDir(generateTemporaryFileName(QDir::tempPath() + "/tst_libarchivearchive.XXXXXX"));
+ QVERIFY(QDir().mkpath(baseDir));
+
+ const QString path1 = tempSourceFile(
+ "Source File 1.",
+ baseDir + "/file.XXXXXX"
+ );
+ const QString path2 = tempSourceFile(
+ "Source File 2.",
+ baseDir + "/file.XXXXXX"
+ );
+
+ const QString filename = generateTemporaryFileName() + suffix;
+ LibArchiveArchive target(filename);
+ QVERIFY(target.open(QIODevice::WriteOnly));
+ QVERIFY(target.create(QStringList() << baseDir + "/*"));
+ target.close();
+ QVERIFY(target.open(QIODevice::ReadOnly));
+ QCOMPARE(target.list().count(), 2);
+ target.close();
+
+ QVERIFY(QFile(filename).remove());
+ QVERIFY(QDir(baseDir).removeRecursively());
+ }
+
+ void testCreateArchiveWithSpaces_data()
+ {
+ archiveSuffixesTestData();
+ }
+
+ void testCreateArchiveWithSpaces()
+ {
+ QFETCH(QString, suffix);
+
+ const QString path1 = tempSourceFile(
+ "Source File 1.",
+ QDir::tempPath() + "/temp file with spaces.XXXXXX"
+ );
+ const QString path2 = tempSourceFile(
+ "Source File 2.",
+ QDir::tempPath() + "/temp file with spaces.XXXXXX"
+ );
+
+ const QString filename = QDir::tempPath() + "/target file with spaces" + suffix;
+ LibArchiveArchive target(filename);
+ target.setFilename(filename);
+ QVERIFY(target.open(QIODevice::WriteOnly));
+ QVERIFY(target.create(QStringList() << path1 << path2));
+ target.close();
+ QVERIFY(target.open(QIODevice::ReadOnly));
+ QCOMPARE(target.list().count(), 2);
+ target.close();
+ QVERIFY(QFile(filename).remove());
+ }
+
+ void testExtractArchive_data()
+ {
+ archiveFilenamesTestData();
+ }
+
+ void testExtractArchive()
+ {
+ QFETCH(QString, filename);
+
+ LibArchiveArchive source(filename);
+ QVERIFY(source.open(QIODevice::ReadOnly));
+
+ QVERIFY(source.extract(QDir::tempPath()));
+ QCOMPARE(QFile::exists(QDir::tempPath() + QString("/valid")), true);
+ QVERIFY(QFile(QDir::tempPath() + QString("/valid")).remove());
+ }
+
+ void testCreateExtractWithSymlink_data()
+ {
+ archiveSuffixesTestData();
+ }
+
+ void testCreateExtractWithSymlink()
+ {
+ QFETCH(QString, suffix);
+
+ const QString workingDir = generateTemporaryFileName() + "/";
+ const QString archiveName = workingDir + "archive" + suffix;
+ const QString targetName = workingDir + "target/";
+#ifdef Q_OS_WIN
+ const QString linkName = workingDir + "link.lnk";
+#else
+ const QString linkName = workingDir + "link";
+#endif
+
+ QVERIFY(QDir().mkpath(targetName));
+
+ QFile source(workingDir + "file");
+ QVERIFY(source.open(QIODevice::ReadWrite));
+ QVERIFY(source.write("Source File"));
+
+ // Creates a shortcut on Windows, a symbolic link on Unix
+ QVERIFY(QFile::link(source.fileName(), linkName));
+
+ LibArchiveArchive archive(archiveName);
+ QVERIFY(archive.open(QIODevice::WriteOnly));
+ QVERIFY(archive.create(QStringList() << source.fileName() << linkName));
+ QVERIFY(QFileInfo::exists(archiveName));
+ archive.close();
+
+ QVERIFY(archive.open(QIODevice::ReadOnly));
+ QVERIFY(archive.extract(targetName));
+ const QString sourceFilename = QFileInfo(source.fileName()).fileName();
+ const QString linkFilename = QFileInfo(linkName).fileName();
+ QVERIFY(QFileInfo::exists(targetName + sourceFilename));
+ QVERIFY(QFileInfo::exists(targetName + linkFilename));
+
+ VerifyInstaller::verifyFileContent(targetName + sourceFilename, source.readAll());
+ const QString sourceFilePath = workingDir + sourceFilename;
+ QCOMPARE(QFile::symLinkTarget(targetName + linkFilename), sourceFilePath);
+
+ archive.close();
+
+ QVERIFY(source.remove());
+ QVERIFY(QFile::remove(archiveName));
+ QVERIFY(QFile::remove(linkName));
+ QVERIFY(QFile::remove(targetName + sourceFilename));
+ QVERIFY(QFile::remove(targetName + linkFilename));
+
+ removeDirectory(targetName, true);
+ removeDirectory(workingDir, true);
+ }
+
+ void testCreateExtractWithUnicodePaths_data()
+ {
+ archiveSuffixesTestData();
+ }
+
+ void testCreateExtractWithUnicodePaths()
+ {
+ QFETCH(QString, suffix);
+
+ const QString targetName = generateTemporaryFileName() + QDir::separator();
+ const QString archiveName = QDir::tempPath() + "/test_archive" + suffix;
+
+ const QString path1 = tempSourceFile(
+ "Source File 1.",
+ QDir::tempPath() + QString::fromUtf8("/测试文件.XXXXXX")
+ );
+ const QString path2 = tempSourceFile(
+ "Source File 2.",
+ QDir::tempPath() + QString::fromUtf8("/тестовый файл.XXXXXX")
+ );
+ const QString path3 = tempSourceFile(
+ "Source File 3.",
+ QDir::tempPath() + QString::fromUtf8("/ملف الاختبار.XXXXXX")
+ );
+
+ LibArchiveArchive archive(archiveName);
+ archive.setFilename(archiveName);
+ QVERIFY(archive.open(QIODevice::WriteOnly));
+ QVERIFY(archive.create(QStringList() << path1 << path2 << path3));
+ archive.close();
+ QVERIFY(archive.open(QIODevice::ReadOnly));
+ QCOMPARE(archive.list().count(), 3);
+
+ QVERIFY(archive.extract(targetName));
+
+ const QString targetPath1 = targetName + QFileInfo(path1).fileName();
+ const QString targetPath2 = targetName + QFileInfo(path2).fileName();
+ const QString targetPath3 = targetName + QFileInfo(path3).fileName();
+
+ QVERIFY(QFileInfo::exists(targetPath1));
+ QVERIFY(QFileInfo::exists(targetPath2));
+ QVERIFY(QFileInfo::exists(targetPath3));
+
+ archive.close();
+ QVERIFY(QFile::remove(archiveName));
+ QVERIFY(QDir(targetName).removeRecursively());
+ }
+
+private:
+ void archiveFilenamesTestData()
+ {
+ QTest::addColumn<QString>("filename");
+ QTest::newRow("ZIP archive") << ":///data/valid.zip";
+ QTest::newRow("gzip compressed tar archive") << ":///data/valid.tar.gz";
+ QTest::newRow("bzip2 compressed tar archive") << ":///data/valid.tar.bz2";
+ QTest::newRow("xz compressed tar archive") << ":///data/valid.tar.xz";
+ QTest::newRow("7zip archive") << ":///data/valid.7z";
+ QTest::newRow("QBSP archive (7z)") << ":///data/valid.qbsp";
+ }
+
+ void archiveSuffixesTestData()
+ {
+ QTest::addColumn<QString>("suffix");
+ QTest::newRow("ZIP archive") << ".zip";
+ QTest::newRow("uncompressed tar archive") << ".tar";
+ QTest::newRow("gzip compressed tar archive") << ".tar.gz";
+ QTest::newRow("bzip2 compressed tar archive") << ".tar.bz2";
+ QTest::newRow("xz compressed tar archive") << ".tar.xz";
+ QTest::newRow("7z archive") << ".7z";
+ QTest::newRow("QBSP archive") << ".qbsp";
+ }
+
+ QString tempSourceFile(const QByteArray &data, const QString &templateName = QString())
+ {
+ QTemporaryFile source;
+ if (!templateName.isEmpty()) {
+ source.setFileTemplate(templateName);
+ }
+ source.open();
+ source.write(data);
+ source.setAutoRemove(false);
+ return source.fileName();
+ }
+
+private:
+ ArchiveEntry m_file;
+};
+
+QTEST_MAIN(tst_libarchivearchive)
+
+#include "tst_libarchivearchive.moc"
diff --git a/tests/auto/installer/licenseagreement/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/licenseagreement/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..d473ac487
--- /dev/null
+++ b/tests/auto/installer/licenseagreement/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/licenseagreement/data/repository/Updates.xml b/tests/auto/installer/licenseagreement/data/repository/Updates.xml
new file mode 100644
index 000000000..c57918162
--- /dev/null
+++ b/tests/auto/installer/licenseagreement/data/repository/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <SHA1>f46c677db8bc779d70d0c72fae264a321caea6f8</SHA1>
+ <Licenses>
+ <License name="GNU GENERAL PUBLIC LICENSE Version 3" file="gpl3.txt"/>
+ </Licenses>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/licenseagreement/licenseagreement.pro b/tests/auto/installer/licenseagreement/licenseagreement.pro
new file mode 100644
index 000000000..e0d7e98d3
--- /dev/null
+++ b/tests/auto/installer/licenseagreement/licenseagreement.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_licenseagreement.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/licenseagreement/settings.qrc b/tests/auto/installer/licenseagreement/settings.qrc
new file mode 100644
index 000000000..d030220ab
--- /dev/null
+++ b/tests/auto/installer/licenseagreement/settings.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/licenseagreement/tst_licenseagreement.cpp b/tests/auto/installer/licenseagreement/tst_licenseagreement.cpp
new file mode 100644
index 000000000..9ba729b10
--- /dev/null
+++ b/tests/auto/installer/licenseagreement/tst_licenseagreement.cpp
@@ -0,0 +1,63 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+
+#include <packagemanagercore.h>
+
+#include <QFile>
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_licenseagreement : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testAutoAcceptFromCLI()
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, ":///data/repository");
+
+ core->setAutoAcceptLicenses();
+ core->installDefaultComponentsSilently();
+
+ QFile file(installDir + "/Licenses/gpl3.txt");
+ QVERIFY(file.exists());
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+};
+
+QTEST_MAIN(tst_licenseagreement)
+
+#include "tst_licenseagreement.moc"
diff --git a/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1content.7z b/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..8ba90b13b
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1content.7z.sha1 b/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1content.7z.sha1
new file mode 100644
index 000000000..a5f4399b3
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1content.7z.sha1
@@ -0,0 +1 @@
+a0268f80fd2954271fe7d2eae584c13a6d143838 \ No newline at end of file
diff --git a/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..d0ed97a7f
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/linereplaceoperation/data/repository/Updates.xml b/tests/auto/installer/linereplaceoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..32b4e787d
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/data/repository/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6d7a3e15d11a4d94b81452fc2aa18e705a01c922</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/A/1.0.2-1content.7z b/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..8ba90b13b
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/A/1.0.2-1content.7z.sha1 b/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/A/1.0.2-1content.7z.sha1
new file mode 100644
index 000000000..a5f4399b3
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/A/1.0.2-1content.7z.sha1
@@ -0,0 +1 @@
+a0268f80fd2954271fe7d2eae584c13a6d143838 \ No newline at end of file
diff --git a/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..131a2d9ff
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,23 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6d7a3e15d11a4d94b81452fc2aa18e705a01c922</SHA1>
+ <Operations>
+ <Operation name="LineReplace">
+ <Argument>@TargetDir@/A.txt</Argument>
+ <Argument>Line to replace.</Argument>
+ <Argument>This line was replaced.</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/linereplaceoperation/linereplaceoperation.pro b/tests/auto/installer/linereplaceoperation/linereplaceoperation.pro
new file mode 100644
index 000000000..87d0c97f4
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/linereplaceoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_linereplaceoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/linereplaceoperation/settings.qrc b/tests/auto/installer/linereplaceoperation/settings.qrc
new file mode 100644
index 000000000..15da313dd
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/settings.qrc
@@ -0,0 +1,11 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1content.7z</file>
+ <file>data/repository/A/1.0.2-1content.7z.sha1</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ <file>data/xmloperationrepository/A/1.0.2-1content.7z</file>
+ <file>data/xmloperationrepository/A/1.0.2-1content.7z.sha1</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/linereplaceoperation/tst_linereplaceoperation.cpp b/tests/auto/installer/linereplaceoperation/tst_linereplaceoperation.cpp
new file mode 100644
index 000000000..5c98d7f8b
--- /dev/null
+++ b/tests/auto/installer/linereplaceoperation/tst_linereplaceoperation.cpp
@@ -0,0 +1,153 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+
+#include <linereplaceoperation.h>
+#include <packagemanagercore.h>
+
+#include <QFile>
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_linereplaceoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (installDir, repository));
+ core->installDefaultComponentsSilently();
+
+ QFile file(installDir + QDir::separator() + "A.txt");
+ QVERIFY(file.open(QIODevice::ReadOnly) | QIODevice::Text);
+ QTextStream stream(&file);
+ QCOMPARE(stream.readLine(), QLatin1String("This line was replaced."));
+ QCOMPARE(stream.readLine(), QLatin1String("Another line."));
+ file.close();
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_testFilePath = qApp->applicationDirPath() + QDir::toNativeSeparators("/test");
+ }
+
+ void testMissingArguments()
+ {
+ LineReplaceOperation op(nullptr);
+
+ op.backup();
+
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in LineReplace: "
+ "0 arguments given, exactly 3 arguments expected."));
+
+ op.setArguments(QStringList() << m_testFilePath << "" << "replace");
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid argument in LineReplace: "
+ "Empty search argument is not supported."));
+
+ op.setArguments(QStringList() << "" << "search" << "replace");
+ QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified");
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError);
+ QCOMPARE(op.errorString(), QString("Cannot open file \"\" for reading: No file name specified"));
+ }
+
+ void testSearchReplace_data()
+ {
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QString>("search");
+ QTest::addColumn<QString>("replace");
+ QTest::addColumn<QString>("expected");
+ QTest::newRow("Lorem ipsum") << "Lorem ipsum dolore sit amet, consectetur adipiscing elit,\n"
+ "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." << "Lorem" << "Replaced"
+ << "Replaced\nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n";
+ QTest::newRow(".ini syntax") << "[section]\na=x\nb=y" << "a=" << "a=y" << "[section]\na=y\nb=y\n";
+ QTest::newRow(".xml syntax") << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Test>\n<Tag></Tag>\n"
+ "</Test>" << "<Tag></Tag>" << "<Tag>el</Tag>" << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<Test>\n<Tag>el</Tag>\n</Test>\n";
+ }
+
+ void testSearchReplace()
+ {
+ QFETCH(QString, source);
+ QFETCH(QString, search);
+ QFETCH(QString, replace);
+ QFETCH(QString, expected);
+
+ QFile file(m_testFilePath);
+ QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
+
+ QTextStream stream(&file);
+ stream << source << Qt::endl;
+ file.close();
+
+ LineReplaceOperation op(nullptr);
+ op.setArguments(QStringList() << m_testFilePath << search << replace);
+
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ QCOMPARE(stream.readAll(), expected);
+
+ file.close();
+ QVERIFY(file.remove());
+ }
+
+ void testLineReplaceFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testLineReplaceFromXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+
+private:
+ QString m_testFilePath;
+};
+
+QTEST_MAIN(tst_linereplaceoperation)
+
+#include "tst_linereplaceoperation.moc"
diff --git a/tests/auto/installer/messageboxhandler/data/invalidhash/B/1.0.0-1content.7z b/tests/auto/installer/messageboxhandler/data/invalidhash/B/1.0.0-1content.7z
new file mode 100644
index 000000000..4663e2b7c
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/invalidhash/B/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/messageboxhandler/data/invalidhash/B/1.0.0-1content.7z.sha1 b/tests/auto/installer/messageboxhandler/data/invalidhash/B/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..281381b97
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/invalidhash/B/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+1c99fe9980cb71dde6a8468c9aa09b4153bc3bff \ No newline at end of file
diff --git a/tests/auto/installer/messageboxhandler/data/invalidhash/Updates.xml b/tests/auto/installer/messageboxhandler/data/invalidhash/Updates.xml
new file mode 100644
index 000000000..2dd2ca2d5
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/invalidhash/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile UncompressedSize="74" OS="Any" CompressedSize="224"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/messageboxhandler/data/invalidoperation/A/1.0.2-1meta.7z b/tests/auto/installer/messageboxhandler/data/invalidoperation/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..f51ed49fa
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/invalidoperation/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/messageboxhandler/data/invalidoperation/Updates.xml b/tests/auto/installer/messageboxhandler/data/invalidoperation/Updates.xml
new file mode 100644
index 000000000..f92211497
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/invalidoperation/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>c8eb49045188859100716ab084452b32fca38d5d</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/messageboxhandler/data/messagebox/A/1.0.2-1meta.7z b/tests/auto/installer/messageboxhandler/data/messagebox/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..3c2832174
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/messagebox/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/messageboxhandler/data/messagebox/Updates.xml b/tests/auto/installer/messageboxhandler/data/messagebox/Updates.xml
new file mode 100644
index 000000000..0781dcfc5
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/messagebox/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>ad3157ed059e3369c094e154319de1d255865de5</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/messageboxhandler/data/missingarchive/C/1.0.0content.7z.sha1 b/tests/auto/installer/messageboxhandler/data/missingarchive/C/1.0.0content.7z.sha1
new file mode 100644
index 000000000..281381b97
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/missingarchive/C/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+1c99fe9980cb71dde6a8468c9aa09b4153bc3bff \ No newline at end of file
diff --git a/tests/auto/installer/messageboxhandler/data/missingarchive/Updates.xml b/tests/auto/installer/messageboxhandler/data/missingarchive/Updates.xml
new file mode 100644
index 000000000..0c5f7e211
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/data/missingarchive/Updates.xml
@@ -0,0 +1,16 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3c940d54a1643ae8020162797860e827f8d246ca</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/messageboxhandler/messageboxhandler.pro b/tests/auto/installer/messageboxhandler/messageboxhandler.pro
index c63b2e35b..3f42aae7b 100644
--- a/tests/auto/installer/messageboxhandler/messageboxhandler.pro
+++ b/tests/auto/installer/messageboxhandler/messageboxhandler.pro
@@ -1,5 +1,7 @@
include(../../qttest.pri)
-QT += qml widgets
-
SOURCES += tst_messageboxhandler.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/messageboxhandler/settings.qrc b/tests/auto/installer/messageboxhandler/settings.qrc
new file mode 100644
index 000000000..2e0d88a2b
--- /dev/null
+++ b/tests/auto/installer/messageboxhandler/settings.qrc
@@ -0,0 +1,13 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/invalidhash/Updates.xml</file>
+ <file>data/invalidhash/B/1.0.0-1content.7z</file>
+ <file>data/invalidhash/B/1.0.0-1content.7z.sha1</file>
+ <file>data/invalidoperation/Updates.xml</file>
+ <file>data/invalidoperation/A/1.0.2-1meta.7z</file>
+ <file>data/missingarchive/Updates.xml</file>
+ <file>data/missingarchive/C/1.0.0content.7z.sha1</file>
+ <file>data/messagebox/Updates.xml</file>
+ <file>data/messagebox/A/1.0.2-1meta.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp b/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp
index dd127f626..5db79cc55 100644
--- a/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp
+++ b/tests/auto/installer/messageboxhandler/tst_messageboxhandler.cpp
@@ -1,7 +1,42 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
#include <messageboxhandler.h>
#include <qinstallerglobal.h>
#include <scriptengine.h>
#include <packagemanagercore.h>
+#include <component.h>
+#include <utils.h>
+#include <fileutils.h>
+#include <binarycontent.h>
+#include <packagemanagercore.h>
+#include <settings.h>
+#include <init.h>
#include <QTest>
#include <QMetaEnum>
@@ -26,7 +61,15 @@ QT_END_NAMESPACE
class tst_MessageBoxHandler : public QObject
{
Q_OBJECT
-public:
+private:
+ void setRepository(const QString &repository) {
+ core->cancelMetaInfoJob();
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(repository);
+ repoList.insert(repo);
+ core->settings().setDefaultRepositories(repoList);
+ }
+
private slots:
void initTestCase()
{
@@ -46,12 +89,22 @@ private slots:
if (enumValue == QMessageBox::LastButton)
break;
}
+
+ QInstaller::init(); //This will eat debug output
+
+ core = new PackageManagerCore(BinaryContent::MagicInstallerMarker, QList<OperationBlob> (),
+ QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production,
+ QHash<QString, QString>(), true);
+ core->disableWriteMaintenanceTool();
+ core->setAutoConfirmCommand();
+ m_installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_installDir));
+ core->setValue(scTargetDir, m_installDir);
}
void testScriptButtonValues()
{
- PackageManagerCore core;
- ScriptEngine *scriptEngine = new ScriptEngine(&core);
+ ScriptEngine *scriptEngine = new ScriptEngine(core);
QMapIterator<QMessageBox::StandardButton, QString> i(m_standardButtonValueMap);
while (i.hasNext()) {
i.next();
@@ -67,8 +120,6 @@ private slots:
void testDefaultAction()
{
- const char ignoreMessage[] = "Created critical message box \"TestError\": \"A test error\", "
- "\"This is a test error message.\"";
srand(time(0)); /* initialize random seed: */
int standardButtons = QMessageBox::NoButton;
@@ -82,8 +133,6 @@ private slots:
// use only every 5th run to reduce the time which it takes to run this test
if (iSecret > 2)
continue;
-
- QTest::ignoreMessage(QtDebugMsg, ignoreMessage);
int returnButton = MessageBoxHandler::instance()->critical(QLatin1String("TestError"),
QLatin1String("A test error"), QLatin1String("This is a test error message."),
static_cast<QMessageBox::StandardButton>(standardButtons));
@@ -101,11 +150,93 @@ private slots:
} while (standardButtons < m_maxStandardButtons);
}
+ void invalidOperationAutoReject()
+ {
+ setRepository(":///data/invalidoperation");
+ core->autoRejectMessageBoxes();
+ core->installDefaultComponentsSilently();
+ QCOMPARE(PackageManagerCore::Canceled, core->status());
+ }
+
+ void invalidOperationAutoAccept()
+ {
+ setRepository(":///data/invalidoperation");
+ core->autoAcceptMessageBoxes();
+ core->installDefaultComponentsSilently();
+ QCOMPARE(PackageManagerCore::Success, core->status());
+ }
+
+ void invalidHashAutoReject()
+ {
+ setRepository(":///data/invalidhash");
+ core->autoRejectMessageBoxes();
+ core->installSelectedComponentsSilently(QStringList () << "B");
+ QCOMPARE(PackageManagerCore::Failure, core->status());
+ }
+
+ void invalidHashAutoAccept()
+ {
+ setRepository(":///data/invalidhash");
+ core->autoAcceptMessageBoxes();
+ core->installSelectedComponentsSilently(QStringList () << "B");
+ QCOMPARE(PackageManagerCore::Failure, core->status());
+ }
+
+ void missingArchiveAutoReject()
+ {
+ setRepository(":///data/missingarchive");
+ core->autoRejectMessageBoxes();
+ core->installSelectedComponentsSilently(QStringList () << "C");
+ QCOMPARE(PackageManagerCore::Canceled, core->status());
+ }
+
+ void missingArchiveAutoAccept()
+ {
+ setRepository(":///data/missingarchive");
+ core->autoAcceptMessageBoxes();
+ core->installSelectedComponentsSilently(QStringList () << "C");
+ QCOMPARE(PackageManagerCore::Failure, core->status()); // Fails after retrying
+ }
+
+ void messageBoxFromScriptDefaultAnswer()
+ {
+ setRepository(":///data/messagebox");
+ core->acceptMessageBoxDefaultButton();
+ core->installSelectedComponentsSilently(QStringList () << "A");
+
+ // These values are written in script based on default
+ // messagebox query results.
+ QCOMPARE(core->value("test.question.default.ok"), QLatin1String("Ok"));
+ QCOMPARE(core->value("test.question.default.cancel"), QLatin1String("Cancel"));
+ }
+
+ void messageBoxFromScriptAutoAnswer()
+ {
+ setRepository(":///data/messagebox");
+ core->setMessageBoxAutomaticAnswer("test.question.default.ok", QMessageBox::Cancel);
+ core->setMessageBoxAutomaticAnswer("test.question.default.cancel", QMessageBox::Ok);
+ core->installSelectedComponentsSilently(QStringList () << "A");
+
+ // These values are written in script based on
+ // messagebox query results.
+ QCOMPARE(core->value("test.question.default.ok"), QLatin1String("Cancel"));
+ QCOMPARE(core->value("test.question.default.cancel"), QLatin1String("Ok"));
+ }
+
+ void cleanupTestCase()
+ {
+ core->deleteLater();
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
private:
QMap<QMessageBox::StandardButton, QString> m_standardButtonValueMap;
int m_maxStandardButtons;
+ PackageManagerCore *core;
+ QString m_installDir;
};
-QTEST_MAIN(tst_MessageBoxHandler)
+QTEST_GUILESS_MAIN(tst_MessageBoxHandler)
#include "tst_messageboxhandler.moc"
diff --git a/tests/auto/installer/metadatacache/data/existing-cache/manifest.json b/tests/auto/installer/metadatacache/data/existing-cache/manifest.json
new file mode 100644
index 000000000..7f30e0fc0
--- /dev/null
+++ b/tests/auto/installer/metadatacache/data/existing-cache/manifest.json
@@ -0,0 +1,7 @@
+{
+ "items": [
+ "placeholder_sha1"
+ ],
+ "type": "Metadata",
+ "version": "1.2.0"
+}
diff --git a/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/Updates.xml b/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/Updates.xml
new file mode 100644
index 000000000..b0b30c9d4
--- /dev/null
+++ b/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/Updates.xml
@@ -0,0 +1,19 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <RepositoryUpdate>
+ <Repository action="remove" url="../repository"/>
+ </RepositoryUpdate>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>5b3939da1af492382c68388fc796837e4c36b876</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/repository.txt b/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/repository.txt
new file mode 100644
index 000000000..7224edd52
--- /dev/null
+++ b/tests/auto/installer/metadatacache/data/existing-cache/placeholder_sha1/repository.txt
@@ -0,0 +1 @@
+/example-repository
diff --git a/tests/auto/installer/metadatacache/data/local-temp-repository/A/example-license.txt b/tests/auto/installer/metadatacache/data/local-temp-repository/A/example-license.txt
new file mode 100644
index 000000000..1ffdcc8df
--- /dev/null
+++ b/tests/auto/installer/metadatacache/data/local-temp-repository/A/example-license.txt
@@ -0,0 +1 @@
+Example license file
diff --git a/tests/auto/installer/metadatacache/data/local-temp-repository/Updates.xml b/tests/auto/installer/metadatacache/data/local-temp-repository/Updates.xml
new file mode 100644
index 000000000..03e54572d
--- /dev/null
+++ b/tests/auto/installer/metadatacache/data/local-temp-repository/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <SHA1>f46c677db8bc779d70d0c72fae264a321caea6f8</SHA1>
+ <Licenses>
+ <License name="Example license" file="example-license.txt"/>
+ </Licenses>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/metadatacache/metadatacache.pro b/tests/auto/installer/metadatacache/metadatacache.pro
new file mode 100644
index 000000000..df1542dc7
--- /dev/null
+++ b/tests/auto/installer/metadatacache/metadatacache.pro
@@ -0,0 +1,8 @@
+include(../../qttest.pri)
+
+QT += qml
+
+SOURCES += tst_metadatacache.cpp
+
+RESOURCES += \
+ settings.qrc
diff --git a/tests/auto/installer/metadatacache/settings.qrc b/tests/auto/installer/metadatacache/settings.qrc
new file mode 100644
index 000000000..96383fdcb
--- /dev/null
+++ b/tests/auto/installer/metadatacache/settings.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/local-temp-repository/Updates.xml</file>
+ <file>data/local-temp-repository/A/example-license.txt</file>
+ <file>data/existing-cache/manifest.json</file>
+ <file>data/existing-cache/placeholder_sha1/repository.txt</file>
+ <file>data/existing-cache/placeholder_sha1/Updates.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/metadatacache/tst_metadatacache.cpp b/tests/auto/installer/metadatacache/tst_metadatacache.cpp
new file mode 100644
index 000000000..ce97de9da
--- /dev/null
+++ b/tests/auto/installer/metadatacache/tst_metadatacache.cpp
@@ -0,0 +1,381 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+
+#include <errors.h>
+#include <fileutils.h>
+#include <metadatacache.h>
+#include <metadata.h>
+#include <repository.h>
+
+#include <QCryptographicHash>
+#include <QDir>
+#include <QFileInfo>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QObject>
+#include <QTest>
+
+#define QUOTE_(x) #x
+#define QUOTE(x) QUOTE_(x)
+
+using namespace QInstaller;
+
+static const QByteArray scPlaceholderSha1("placeholder_sha1");
+
+class tst_metadatacache : public QObject
+{
+ Q_OBJECT
+
+private:
+ void copyExistingCacheFromResourceTree()
+ {
+ try {
+ QInstaller::copyDirectoryContents(":/data/existing-cache/", m_cachePath);
+
+ // We need to modify the test data here because the checksums of
+ // files may differ on Windows and Unix platforms.
+ QVERIFY(QDir().rename(m_cachePath + QDir::separator() + scPlaceholderSha1,
+ m_cachePath + QDir::separator() + m_oldMetadataItemChecksum));
+
+ QFile manifestFile(m_cachePath + QDir::separator() + "manifest.json");
+ // The file lost the write bit after copying from resource
+ QInstaller::setDefaultFilePermissions(&manifestFile, QInstaller::NonExecutable);
+ QVERIFY2(manifestFile.open(QIODevice::ReadWrite), qPrintable(manifestFile.errorString()));
+
+ const QByteArray manifestData = manifestFile.readAll();
+ QJsonDocument manifestJsonDoc(QJsonDocument::fromJson(manifestData));
+ QJsonObject docJsonObject = manifestJsonDoc.object();
+
+ QJsonArray itemsJsonArray;
+ itemsJsonArray.append(QJsonValue(QLatin1String(m_oldMetadataItemChecksum)));
+
+ docJsonObject.insert(QLatin1String("items"), itemsJsonArray);
+ manifestJsonDoc.setObject(docJsonObject);
+
+ manifestFile.seek(0);
+ QVERIFY(manifestFile.write(manifestJsonDoc.toJson()) != -1);
+
+ } catch (const Error &e) {
+ QVERIFY2(false, QString::fromLatin1("Error while copying item to path %1: %2")
+ .arg(m_cachePath, e.message()).toLatin1());
+ }
+ }
+
+ QStringList itemsFromManifest(const QString &manifestPath)
+ {
+ QFile manifestFile(manifestPath);
+ if (!manifestFile.open(QIODevice::ReadOnly))
+ return QStringList();
+
+ const QByteArray manifestData = manifestFile.readAll();
+ const QJsonDocument manifestJsonDoc(QJsonDocument::fromJson(manifestData));
+ const QJsonObject docJsonObject = manifestJsonDoc.object();
+ const QJsonArray itemsJsonArray = docJsonObject.value(QLatin1String("items")).toArray();
+
+ QStringList items;
+ for (const auto &itemJsonValue : itemsJsonArray)
+ items << itemJsonValue.toString();
+
+ return items;
+ }
+
+ QByteArray checksumFromUpdateFile(const QString &directory)
+ {
+ QFile updateFile(directory + QDir::separator() + QLatin1String("Updates.xml"));
+ if (!updateFile.open(QIODevice::ReadOnly))
+ return QByteArray();
+
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(&updateFile);
+ return hash.result().toHex();
+ }
+
+private slots:
+ void init()
+ {
+ m_cachePath = generateTemporaryFileName();
+ }
+
+ void cleanup()
+ {
+ if (QFileInfo::exists(m_cachePath))
+ QInstaller::removeDirectory(m_cachePath, true);
+ }
+
+ void initTestCase()
+ {
+ m_newMetadataItemChecksum = checksumFromUpdateFile(":/data/local-temp-repository");
+ m_oldMetadataItemChecksum = checksumFromUpdateFile(":/data/existing-cache/"
+ + QLatin1String(scPlaceholderSha1));
+
+ QVERIFY(!m_newMetadataItemChecksum.isEmpty());
+ QVERIFY(!m_oldMetadataItemChecksum.isEmpty());
+
+ qInstallMessageHandler(silentTestMessageHandler);
+ }
+
+ void testRegisterItemToEmptyCache()
+ {
+ MetadataCache cache(m_cachePath);
+ Metadata *metadata = new Metadata(":/data/local-temp-repository/");
+
+ QVERIFY(cache.registerItem(metadata));
+ metadata = cache.itemByChecksum(m_newMetadataItemChecksum);
+ QVERIFY(metadata);
+ QVERIFY(metadata->isValid());
+ QVERIFY(!QFileInfo::exists(m_cachePath + "/manifest.json"));
+ QVERIFY(cache.sync());
+ QVERIFY(itemsFromManifest(m_cachePath + "/manifest.json").contains(QLatin1String(m_newMetadataItemChecksum)));
+
+ QVERIFY(cache.clear());
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testRegisterItemToExistingCache()
+ {
+ copyExistingCacheFromResourceTree();
+
+ MetadataCache cache(m_cachePath);
+ Metadata *metadata = new Metadata(":/data/local-temp-repository/");
+ QVERIFY(itemsFromManifest(m_cachePath + "/manifest.json").contains(QLatin1String(m_oldMetadataItemChecksum)));
+
+ QVERIFY(cache.registerItem(metadata));
+ metadata = cache.itemByChecksum(m_newMetadataItemChecksum);
+ QVERIFY(metadata);
+ QVERIFY(metadata->isValid());
+ QVERIFY(cache.sync());
+ const QStringList manifestItems = itemsFromManifest(m_cachePath + "/manifest.json");
+ QVERIFY(manifestItems.contains(QLatin1String(m_oldMetadataItemChecksum)));
+ QVERIFY(manifestItems.contains(QLatin1String(m_newMetadataItemChecksum)));
+
+ QVERIFY(cache.clear());
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testRegisterItemFails()
+ {
+ // 1. Test fail due to invalidated cache
+ MetadataCache cache;
+ Metadata *metadata = new Metadata(":/data/local-temp-repository/");
+
+ QVERIFY(!cache.registerItem(metadata));
+ QCOMPARE(cache.errorString(), "Cannot register item to invalidated cache.");
+
+ delete metadata;
+ metadata = nullptr;
+
+ // 2. Test fail due to null metadata
+ cache.setPath(m_cachePath);
+ cache.setType("Metadata");
+ cache.setVersion(QUOTE(IFW_CACHE_FORMAT_VERSION));
+ QVERIFY(cache.initialize());
+
+ QVERIFY(!cache.registerItem(metadata));
+ QCOMPARE(cache.errorString(), "Cannot register null item.");
+
+ // 3. Test fail due to invalid metadata
+ metadata = new Metadata;
+ QVERIFY(!cache.registerItem(metadata));
+ QCOMPARE(cache.errorString(), "Cannot register invalid item with checksum ");
+
+ // 4. Test fail due to duplicate metadata item
+ metadata->setPath(":/data/local-temp-repository/");
+ QVERIFY(cache.registerItem(metadata));
+ QVERIFY(cache.itemByChecksum(m_newMetadataItemChecksum)->isValid());
+ QVERIFY(!cache.registerItem(metadata));
+ QCOMPARE(cache.errorString(), QString::fromLatin1("Cannot register item with checksum "
+ "%1. An item with the same checksum already exists in cache.")
+ .arg(QString::fromLatin1(m_newMetadataItemChecksum)).toLatin1());
+
+ QVERIFY(cache.clear());
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testInitializeExistingCache()
+ {
+ copyExistingCacheFromResourceTree();
+
+ MetadataCache cache(m_cachePath);
+ Metadata *metadata = cache.itemByChecksum(m_oldMetadataItemChecksum);
+ QVERIFY(metadata);
+ QVERIFY(metadata->isValid());
+
+ QVERIFY(cache.clear());
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testInitializeForeignCache_data()
+ {
+ QTest::addColumn<QString>("type");
+ QTest::addColumn<QString>("version");
+
+ QTest::newRow("Type mismatch") << "MyCacheableType" << QUOTE(IFW_CACHE_FORMAT_VERSION);
+ QTest::newRow("Version mismatch") << "Metadata" << "0.9.1";
+ }
+
+ void testInitializeForeignCache()
+ {
+ QFETCH(QString, type);
+ QFETCH(QString, version);
+
+ copyExistingCacheFromResourceTree();
+
+ MetadataCache cache;
+ cache.setType(type);
+ cache.setVersion(version);
+ cache.setPath(m_cachePath);
+ QVERIFY(cache.initialize());
+
+ QVERIFY(cache.isValid());
+ QVERIFY(!cache.itemByChecksum(m_oldMetadataItemChecksum));
+
+ QVERIFY(cache.clear());
+ // The 'foreign' entry prevents removing the directory
+ QVERIFY(QFileInfo::exists(m_cachePath));
+ }
+
+ void testInitializeCacheFails()
+ {
+ MetadataCache cache;
+ QVERIFY(!cache.initialize());
+ QCOMPARE(cache.errorString(), "Cannot initialize cache with empty path.");
+ }
+
+ void testRemoveItemFromCache()
+ {
+ copyExistingCacheFromResourceTree();
+
+ MetadataCache cache(m_cachePath);
+ Metadata *metadata = cache.itemByChecksum(m_oldMetadataItemChecksum);
+ QVERIFY(metadata);
+ QVERIFY(metadata->isValid());
+ QVERIFY(cache.removeItem(m_oldMetadataItemChecksum));
+
+ QVERIFY(cache.clear());
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testRemoveItemFails()
+ {
+ copyExistingCacheFromResourceTree();
+
+ MetadataCache cache(m_cachePath);
+ QVERIFY(!cache.removeItem("12345"));
+ QCOMPARE(cache.errorString(), "Cannot remove item specified by checksum 12345: no such item exists.");
+
+ QVERIFY(cache.clear());
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testRetrieveItemFromCache()
+ {
+ MetadataCache cache(m_cachePath);
+ Metadata *metadata = new Metadata(":/data/local-temp-repository/");
+
+ QVERIFY(cache.registerItem(metadata));
+ metadata = cache.itemByChecksum(m_newMetadataItemChecksum);
+ QVERIFY(metadata);
+ QVERIFY(metadata->isValid());
+
+ metadata = cache.itemByPath(metadata->path());
+ QVERIFY(metadata);
+ QVERIFY(metadata->isValid());
+
+ QVERIFY(cache.clear());
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testRetrieveItemFails()
+ {
+ MetadataCache cache(m_cachePath);
+ Metadata *metadata = new Metadata(":/data/local-temp-repository/");
+ const QString metadataPath = metadata->path();
+
+ QVERIFY(cache.registerItem(metadata));
+ QVERIFY(cache.clear());
+
+ QVERIFY(!cache.itemByChecksum(m_newMetadataItemChecksum));
+ QVERIFY(!cache.itemByPath(metadataPath));
+ QCOMPARE(cache.errorString(), "Cannot retrieve item from invalidated cache.");
+
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testItemObsoletesOther()
+ {
+ copyExistingCacheFromResourceTree();
+
+ MetadataCache cache(m_cachePath);
+ Metadata *metadata = new Metadata(":/data/local-temp-repository/");
+
+ QVERIFY(cache.registerItem(metadata));
+ metadata->setRepository(Repository(QUrl("file:///example-repository"), true));
+ metadata->setPersistentRepositoryPath(QUrl("file:///example-repository"));
+ QVERIFY(metadata->isActive());
+
+ metadata = cache.itemByChecksum(m_newMetadataItemChecksum);
+ QVERIFY(metadata);
+ QVERIFY(metadata->isValid());
+
+ metadata = cache.itemByChecksum(m_oldMetadataItemChecksum);
+ QVERIFY(metadata);
+ QVERIFY(metadata->isValid());
+
+ Metadata *obsolete = cache.obsoleteItems().first();
+ QVERIFY(!obsolete->isActive());
+ QCOMPARE(obsolete->checksum(), m_oldMetadataItemChecksum);
+
+ QVERIFY(cache.clear());
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+ void testClearCacheFails()
+ {
+ MetadataCache cache(m_cachePath);
+ Metadata *metadata = new Metadata(":/data/local-temp-repository/");
+
+ QVERIFY(cache.registerItem(metadata));
+ QVERIFY(cache.clear());
+ QVERIFY(!cache.clear());
+ QCOMPARE(cache.errorString(), "Cannot clear invalidated cache.");
+
+ QVERIFY(!QFileInfo::exists(m_cachePath));
+ }
+
+private:
+ QString m_cachePath;
+ QByteArray m_newMetadataItemChecksum;
+ QByteArray m_oldMetadataItemChecksum;
+};
+
+QTEST_MAIN(tst_metadatacache)
+
+#include "tst_metadatacache.moc"
diff --git a/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1content.7z b/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1content.7z
new file mode 100644
index 000000000..7d03dca9c
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1content.7z.sha1 b/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..91ead97f0
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+c8b7076fabaaf6b9d27f27350c577118c24f426b \ No newline at end of file
diff --git a/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1meta.7z b/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1meta.7z
new file mode 100644
index 000000000..46bae0179
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repository/C/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repository/Updates.xml b/tests/auto/installer/metadatajob/data/repository/Updates.xml
new file mode 100644
index 000000000..17d89cda7
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repository/Updates.xml
@@ -0,0 +1,16 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>5b3939da1af492382c68388fc796837e4c36b876</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/metadatajob/data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z b/tests/auto/installer/metadatajob/data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z
new file mode 100644
index 000000000..df1f72b51
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1content.7z b/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1content.7z
new file mode 100644
index 000000000..5a9383e7e
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1content.7z.sha1 b/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1content.7z.sha1
new file mode 100644
index 000000000..fd0bc548c
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1content.7z.sha1
@@ -0,0 +1 @@
+643cb71b2337d5a49d57a5bc3c636ee9b84c0802 \ No newline at end of file
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1meta.7z b/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..6ef0b7959
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionAdd/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1content.7z b/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1content.7z
new file mode 100644
index 000000000..dfe41ad15
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1content.7z.sha1 b/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..50a632b49
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+c7b9ab370efe036171dda7b71cd95021747cb101 \ No newline at end of file
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1meta.7z b/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1meta.7z
new file mode 100644
index 000000000..12d54f94c
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionAdd/B/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionAdd/Updates.xml b/tests/auto/installer/metadatajob/data/repositoryActionAdd/Updates.xml
new file mode 100644
index 000000000..da842bdf7
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionAdd/Updates.xml
@@ -0,0 +1,30 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <RepositoryUpdate>
+ <Repository action="add" url="../repository" displayname="Example repository"/>
+ </RepositoryUpdate>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>9d54e3a5adf3563913feee8ba23a99fb80d46590</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>9170d55a6af81c1a6a63d708a4ab6ed359775cd9</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1content.7z b/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1content.7z
new file mode 100644
index 000000000..7d03dca9c
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1content.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1content.7z.sha1 b/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1content.7z.sha1
new file mode 100644
index 000000000..91ead97f0
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1content.7z.sha1
@@ -0,0 +1 @@
+c8b7076fabaaf6b9d27f27350c577118c24f426b \ No newline at end of file
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1meta.7z b/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1meta.7z
new file mode 100644
index 000000000..46bae0179
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionRemove/C/1.0.0-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/data/repositoryActionRemove/Updates.xml b/tests/auto/installer/metadatajob/data/repositoryActionRemove/Updates.xml
new file mode 100644
index 000000000..b0b30c9d4
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryActionRemove/Updates.xml
@@ -0,0 +1,19 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <RepositoryUpdate>
+ <Repository action="remove" url="../repository"/>
+ </RepositoryUpdate>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="222" OS="Any" UncompressedSize="72"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>5b3939da1af492382c68388fc796837e4c36b876</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/metadatajob/data/repositoryZipped/repositoryZipped.7z b/tests/auto/installer/metadatajob/data/repositoryZipped/repositoryZipped.7z
new file mode 100644
index 000000000..6afaae497
--- /dev/null
+++ b/tests/auto/installer/metadatajob/data/repositoryZipped/repositoryZipped.7z
Binary files differ
diff --git a/tests/auto/installer/metadatajob/metadatajob.pro b/tests/auto/installer/metadatajob/metadatajob.pro
new file mode 100644
index 000000000..2e4b5d2f1
--- /dev/null
+++ b/tests/auto/installer/metadatajob/metadatajob.pro
@@ -0,0 +1,8 @@
+include(../../qttest.pri)
+
+QT += qml
+
+SOURCES += tst_metadatajob.cpp
+
+RESOURCES += \
+ settings.qrc
diff --git a/tests/auto/installer/metadatajob/settings.qrc b/tests/auto/installer/metadatajob/settings.qrc
new file mode 100644
index 000000000..5df3befd9
--- /dev/null
+++ b/tests/auto/installer/metadatajob/settings.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repositoryActionAdd/Updates.xml</file>
+ <file>data/repositoryActionRemove/Updates.xml</file>
+ <file>data/repositoryZipped/repositoryZipped.7z</file>
+ <file>data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/metadatajob/tst_metadatajob.cpp b/tests/auto/installer/metadatajob/tst_metadatajob.cpp
new file mode 100644
index 000000000..cb974e7ad
--- /dev/null
+++ b/tests/auto/installer/metadatajob/tst_metadatajob.cpp
@@ -0,0 +1,148 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "metadatajob.h"
+#include "settings.h"
+
+#include <binarycontent.h>
+#include <component.h>
+#include <errors.h>
+#include <fileutils.h>
+#include <packagemanagercore.h>
+#include <progresscoordinator.h>
+
+#include <QTest>
+
+using namespace QInstaller;
+
+class tst_MetaDataJob : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testRepository()
+ {
+ PackageManagerCore core;
+ core.setInstaller();
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(":///data/repository");
+ repoList.insert(repo);
+ core.settings().setDefaultRepositories(repoList);
+ MetadataJob metadata;
+ metadata.setPackageManagerCore(&core);
+ metadata.start();
+ metadata.waitForFinished();
+ QCOMPARE(metadata.metadata().count(), 1);
+ }
+
+ void testRepositoryUpdateActionAdd()
+ {
+ PackageManagerCore core;
+ core.setInstaller();
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(":///data/repositoryActionAdd");
+ repoList.insert(repo);
+ core.settings().setDefaultRepositories(repoList);
+ MetadataJob metadata;
+ metadata.setPackageManagerCore(&core);
+
+ QTest::ignoreMessage(QtDebugMsg, "Repository to add: \"Example repository\"");
+ QTest::ignoreMessage(QtDebugMsg, "Repository to add: \"Example repository\"");
+ metadata.start();
+ metadata.waitForFinished();
+ QCOMPARE(metadata.metadata().count(), 2);
+ }
+
+ void testRepositoryUpdateActionRemove()
+ {
+ PackageManagerCore core;
+ core.setInstaller();
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(":///data/repositoryActionRemove");
+ Repository repo2 = Repository::fromUserInput(":///data/repository");
+ repoList.insert(repo);
+ repoList.insert(repo2);
+ core.settings().setDefaultRepositories(repoList);
+ MetadataJob metadata;
+ metadata.setPackageManagerCore(&core);
+
+ QTest::ignoreMessage(QtDebugMsg, "Repository to remove: \"file::///data/repository\"");
+ QTest::ignoreMessage(QtDebugMsg, "Repository to remove: \"file::///data/repository\"");
+ metadata.start();
+ metadata.waitForFinished();
+ QCOMPARE(metadata.metadata().count(), 1);
+ }
+
+ void testZippedRepository_data()
+ {
+ QTest::addColumn<QStringList>("repositories");
+ QTest::addColumn<int>("metacount");
+ QTest::addColumn<bool>("allowUnstable");
+
+ QStringList repositories;
+ repositories << ":///data/repositoryZipped/repositoryZipped.7z";
+ QTest::newRow("7z repository") << repositories << 1 << true;
+
+ repositories.clear();
+ repositories << ":///data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z";
+ QTest::newRow("7z with invalid meta sha1") << repositories << 0 << true;
+
+ repositories.clear();
+ repositories << ":///data/repositoryZipped/repositoryZipped.7z" << ":///data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z";
+ QTest::newRow("7z with one valid repository") << repositories << 1 << true;
+
+ repositories.clear();
+ repositories << ":///data/repository7zInvalidMetaSha1/repository7zInvalidMetaSha1.7z" << ":///data/repositoryZipped/repositoryZipped.7z";
+ QTest::newRow("7z with one valid repository") << repositories << 0 << false;
+ }
+
+ void testZippedRepository()
+ {
+ QFETCH(QStringList, repositories);
+ QFETCH(int, metacount);
+ QFETCH(bool, allowUnstable);
+
+ PackageManagerCore core;
+ core.setInstaller();
+ core.setTemporaryRepositories(repositories, false, true);
+ core.settings().setAllowUnstableComponents(allowUnstable);
+
+ MetadataJob metadata;
+ metadata.setPackageManagerCore(&core);
+ metadata.addDownloadType(DownloadType::CompressedPackage);
+ metadata.setAutoDelete(true);
+ metadata.start();
+ metadata.waitForFinished();
+ QCOMPARE(metadata.metadata().count(), metacount);
+ }
+};
+
+
+QTEST_MAIN(tst_MetaDataJob)
+
+#include "tst_metadatajob.moc"
diff --git a/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp b/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp
index f52c27d0f..e41ba8049 100644
--- a/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp
+++ b/tests/auto/installer/mkdiroperationtest/tst_mkdiroperationtest.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2024 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -60,32 +60,42 @@ private slots:
QVERIFY(!op.performOperation());
QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
- QCOMPARE(op.errorString(), QString("Invalid arguments in Mkdir: "
- "0 arguments given, exactly 1 arguments expected."));
-
+ QCOMPARE(op.errorString(), QString("Invalid arguments in Mkdir: 0 arguments given, 1 to 3 "
+ "arguments expected in the form: <file to remove> [UNDOOPERATION, \"\"]."));
}
void testCreateDirectory_data()
{
- QTest::addColumn<QString>("directory");
- QTest::newRow("/test") << "/test";
- QTest::newRow("/test/test") << "/test/test";
- QTest::newRow("/test/test/test") << "/test/test/test";
+ QTest::addColumn<QString>("directory");
+ QTest::addColumn<bool>("overrideUndo");
+ QTest::newRow("/test") << "/test" << false;
+ QTest::newRow("/test/test") << "/test/test" << false;
+ QTest::newRow("/test/test/test") << "/test/test/test" << false;
+ QTest::newRow("no undo") << "/test" << true;
}
void testCreateDirectory()
{
QFETCH(QString, directory);
+ QFETCH(bool, overrideUndo);
+
QString path = QDir::current().path() + QDir::toNativeSeparators(directory);
QVERIFY2(!QDir(path).exists(), path.toLatin1());
MkdirOperation op;
op.setArguments(QStringList() << path);
+ if (overrideUndo)
+ op.setArguments(op.arguments() << QLatin1String("UNDOOPERATION"));
op.backup();
QVERIFY2(op.performOperation(), op.errorString().toLatin1());
QVERIFY2(QDir(path).exists(), path.toLatin1());
QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
- QVERIFY2(!QDir(path).exists(), path.toLatin1());
+ if (overrideUndo) {
+ QVERIFY2(QDir(path).exists(), path.toLatin1());
+ QVERIFY(QDir(path).removeRecursively());
+ } else {
+ QVERIFY2(!QDir(path).exists(), path.toLatin1());
+ }
}
void testCreateDirectory_customFile_data()
diff --git a/tests/auto/installer/moveoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/moveoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..bd8df91b3
--- /dev/null
+++ b/tests/auto/installer/moveoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/moveoperation/data/repository/Updates.xml b/tests/auto/installer/moveoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..5cdad4e45
--- /dev/null
+++ b/tests/auto/installer/moveoperation/data/repository/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>badc75810d399a35bae6f6b2cd8acfc1d5b1ccd2</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/moveoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/moveoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..6707452d8
--- /dev/null
+++ b/tests/auto/installer/moveoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,22 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Operations>
+ <Operation name="Mkdir">
+ <Argument>@TargetDir@/DestinationFolder</Argument>
+ </Operation>
+ <Operation name="Move">
+ <Argument>@InstallerDirPath@/testFile.txt</Argument>
+ <Argument>@TargetDir@/DestinationFolder/testFile.txt</Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/moveoperation/moveoperation.pro b/tests/auto/installer/moveoperation/moveoperation.pro
new file mode 100644
index 000000000..a1195299a
--- /dev/null
+++ b/tests/auto/installer/moveoperation/moveoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_moveoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/moveoperation/settings.qrc b/tests/auto/installer/moveoperation/settings.qrc
new file mode 100644
index 000000000..04a7daf71
--- /dev/null
+++ b/tests/auto/installer/moveoperation/settings.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/moveoperation/tst_moveoperation.cpp b/tests/auto/installer/moveoperation/tst_moveoperation.cpp
new file mode 100644
index 000000000..bb391efee
--- /dev/null
+++ b/tests/auto/installer/moveoperation/tst_moveoperation.cpp
@@ -0,0 +1,151 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+
+#include <updateoperations.h>
+#include <packagemanagercore.h>
+
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_moveoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void installFromCLI(const QString &repository)
+ {
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_testDirectory, repository));
+ core->installDefaultComponentsSilently();
+
+ QFile movedFile(m_testDirectory + QDir::separator() + "DestinationFolder/testFile.txt");
+ QVERIFY(movedFile.exists());
+ QFile originalFile(m_sourceFile);
+ QVERIFY(!originalFile.exists());
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+
+ core->uninstallComponentsSilently(QStringList() << "A");
+
+ QVERIFY(!movedFile.exists());
+ QVERIFY(originalFile.exists());
+ }
+
+private slots:
+ void initTestCase()
+ {
+ m_testDirectory = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_testDirectory));
+ QVERIFY(QDir(m_testDirectory).exists());
+
+ QString testFile = QDir::toNativeSeparators("/testFile.txt");
+ m_sourceFile = qApp->applicationDirPath() + testFile;
+ QFile file(m_sourceFile);
+ QVERIFY(file.open(QIODevice::WriteOnly)); //Generates the m_sourceFile
+ file.close();
+
+ m_destinationDirectory = m_testDirectory + QDir::toNativeSeparators("/test");
+ QVERIFY(QDir().mkpath(m_destinationDirectory));
+ m_destinationFile = m_destinationDirectory + QDir::toNativeSeparators(testFile);
+ }
+
+ void testMissingArguments()
+ {
+ MoveOperation op;
+
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in Move: 0 arguments given, 2 to 4 arguments "
+ "expected in the form: <complete source file name> <complete destination file name> [UNDOOPERATION, \"\"]."));
+ }
+
+ void testMoveFile()
+ {
+ MoveOperation op;
+ op.setArguments(QStringList() << m_sourceFile << m_destinationFile);
+ op.backup();
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFile::exists(m_sourceFile));
+ QVERIFY(QFile::exists(m_destinationFile));
+
+ QVERIFY(op.undoOperation());
+ QVERIFY(QFile::exists(m_sourceFile));
+ QVERIFY(!QFile::exists(m_destinationFile));
+ }
+
+ void testMoveFileDestinationExists()
+ {
+ QFile file(m_destinationFile);
+ QVERIFY(file.open(QIODevice::WriteOnly)); //Creates the destination file
+ file.close();
+
+ MoveOperation op;
+ op.setArguments(QStringList() << m_sourceFile << m_destinationFile);
+ op.backup();
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFile::exists(m_sourceFile));
+ QVERIFY(QFile::exists(m_destinationFile));
+
+ QVERIFY(op.undoOperation());
+ QVERIFY(QFile::exists(m_sourceFile));
+ QVERIFY(QFile::exists(m_destinationFile));
+ }
+
+ void testMoveOperationFromScript()
+ {
+ installFromCLI(":///data/repository");
+ }
+
+ void testMoveOperationFromXML()
+ {
+ installFromCLI(":///data/xmloperationrepository");
+ }
+
+ void cleanupTestCase()
+ {
+ QDir dir(m_testDirectory);
+ QVERIFY(dir.removeRecursively());
+ QVERIFY(QFile::remove(m_sourceFile));
+ }
+
+private:
+ QString m_testDirectory;
+ QString m_sourceFile;
+ QString m_destinationDirectory;
+ QString m_destinationFile;
+};
+
+QTEST_MAIN(tst_moveoperation)
+
+#include "tst_moveoperation.moc"
diff --git a/tests/auto/installer/packagemanagercore/installer-config/config.xml b/tests/auto/installer/packagemanagercore/installer-config/config.xml
index adc24631b..5826308e1 100644
--- a/tests/auto/installer/packagemanagercore/installer-config/config.xml
+++ b/tests/auto/installer/packagemanagercore/installer-config/config.xml
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Installer>
- <Name>test</Name>
+ <Name>Unit Test Application</Name>
+ <Title>Unit Test Application Title</Title>
<Version>1.0.0</Version>
+ <Publisher>The Qt Company</Publisher>
+ <MaintenanceToolName>UnitTestMaintenancetool</MaintenanceToolName>
</Installer>
diff --git a/tests/auto/installer/packagemanagercore/settings.qrc b/tests/auto/installer/packagemanagercore/settings.qrc
index b25a589a3..d7dfb5ddd 100644
--- a/tests/auto/installer/packagemanagercore/settings.qrc
+++ b/tests/auto/installer/packagemanagercore/settings.qrc
@@ -3,3 +3,4 @@
<file>installer-config/config.xml</file>
</qresource>
</RCC>
+
diff --git a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
index 67fa7e2c5..410bfb01c 100644
--- a/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
+++ b/tests/auto/installer/packagemanagercore/tst_packagemanagercore.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,18 +32,21 @@
#include <fileutils.h>
#include <packagemanagercore.h>
#include <progresscoordinator.h>
+#include <init.h>
+#include <settings.h>
#include <QDir>
#include <QFile>
#include <QTemporaryFile>
#include <QTest>
+#include <QRegularExpression>
using namespace QInstaller;
class DummyComponent : public Component
{
public:
- DummyComponent(PackageManagerCore *core)
+ explicit DummyComponent(PackageManagerCore *core)
: Component(core)
{
setCheckState(Qt::Checked);
@@ -257,7 +260,6 @@ private slots:
root->setInstalled();
child1->setInstalled();
child2->setUninstalled();
- core.componentsToInstallNeedsRecalculation();
core.calculateComponentsToInstall();
QCOMPARE(core.requiredDiskSpace(), 250ULL);
}
@@ -285,33 +287,63 @@ private slots:
QVERIFY(QDir().rmdir(testDirectory));
}
- void testSubdirectoriesWritable()
+ void testCoreDataValues()
{
- PackageManagerCore core;
-
- const QString testDirectory = QInstaller::generateTemporaryFileName();
- QVERIFY(QDir().mkpath(testDirectory));
- QVERIFY(QDir(testDirectory).exists());
-
- const QString testSubdirectory = testDirectory + "/" + QString::number(qrand() % 1000);
-
- QVERIFY(QDir().mkpath(testSubdirectory));
- QVERIFY(QDir(testSubdirectory).exists());
+ QHash<QString, QString> userValues;
+
+ PackageManagerCore *core = new PackageManagerCore(BinaryContent::MagicInstallerMarker, QList<OperationBlob> (),
+ QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production,
+ userValues, true);
+ QCOMPARE(core->value("AllUsers"), QLatin1String(""));
+ QCOMPARE(core->value("ProductName"), QLatin1String("Unit Test Application"));
+ QCOMPARE(core->value("ProductVersion"), QLatin1String("1.0.0"));
+ QCOMPARE(core->value("Title"), QLatin1String("Unit Test Application Title"));
+ QCOMPARE(core->value("RootDir"), QDir::rootPath());
+
+ core->deleteLater();
+ core->deleteLater();
+ }
- // should be writable
- QVERIFY(core.subdirectoriesWritable(testDirectory));
+ void testOverwrittenCoreDataValues()
+ {
+ QHash<QString, QString> userValues;
+ userValues.insert("AllUsers", "true");
+ userValues.insert("ProductName", "Overwritten ProductName");
+ userValues.insert("ProductVersion", "2.0.0");
+ userValues.insert("Title", "Overwritten Title");
+ userValues.insert("RootDir", "Overwritten RootDir");
+
+ PackageManagerCore *core = new PackageManagerCore(BinaryContent::MagicInstallerMarker, QList<OperationBlob> (),
+ QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production,
+ userValues, true);
+ QCOMPARE(core->value("AllUsers"), QLatin1String("true"));
+ QCOMPARE(core->value("ProductName"), QLatin1String("Overwritten ProductName"));
+ QCOMPARE(core->value("ProductVersion"), QLatin1String("2.0.0"));
+ QCOMPARE(core->value("Title"), QLatin1String("Overwritten Title"));
+ QCOMPARE(core->value("RootDir"), QLatin1String("Overwritten RootDir"));
+ core->deleteLater();
+ }
-#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
- QFile dirDevice(testSubdirectory);
- dirDevice.setPermissions(QFileDevice::ReadOwner | QFileDevice::ExeOwner);
+ void testToFromNativeSeparators_data()
+ {
+ QTest::addColumn<QString>("path");
+ QTest::newRow("Slash separator") << "a/test/path";
+ QTest::newRow("Backslash separator") << "a\\test\\path";
+ QTest::newRow("Mixed separators") << "a/test\\path";
+ }
- // should not be writable
- QVERIFY(!core.subdirectoriesWritable(testDirectory));
+ void testToFromNativeSeparators()
+ {
+ QFETCH(QString, path);
- dirDevice.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner);
+ PackageManagerCore core;
+#ifdef Q_OS_WIN
+ QCOMPARE(core.toNativeSeparators(path), "a\\test\\path");
+ QCOMPARE(core.fromNativeSeparators(path), "a/test/path");
+#else
+ QCOMPARE(core.toNativeSeparators(path), path);
+ QCOMPARE(core.fromNativeSeparators(path), path);
#endif
- QVERIFY(QDir().rmdir(testSubdirectory));
- QVERIFY(QDir().rmdir(testDirectory));
}
};
diff --git a/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1content.7z b/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1content.7z
new file mode 100644
index 000000000..543aab656
--- /dev/null
+++ b/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1meta.7z b/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1meta.7z
new file mode 100644
index 000000000..a59f269e7
--- /dev/null
+++ b/tests/auto/installer/prependfileoperation/data/repository/B/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/prependfileoperation/data/repository/Updates.xml b/tests/auto/installer/prependfileoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..e61d2445f
--- /dev/null
+++ b/tests/auto/installer/prependfileoperation/data/repository/Updates.xml
@@ -0,0 +1,16 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>750eda14d867849aeb2f47d620f6e5f32134f375</SHA1>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/prependfileoperation/data/xmloperationrepository/C/1.0.0content.7z b/tests/auto/installer/prependfileoperation/data/xmloperationrepository/C/1.0.0content.7z
new file mode 100644
index 000000000..d936db354
--- /dev/null
+++ b/tests/auto/installer/prependfileoperation/data/xmloperationrepository/C/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/prependfileoperation/data/xmloperationrepository/Updates.xml b/tests/auto/installer/prependfileoperation/data/xmloperationrepository/Updates.xml
new file mode 100644
index 000000000..379fe865f
--- /dev/null
+++ b/tests/auto/installer/prependfileoperation/data/xmloperationrepository/Updates.xml
@@ -0,0 +1,20 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2020-01-01</ReleaseDate>
+ <Default>true</Default>
+ <UpdateFile CompressedSize="224" OS="Any" UncompressedSize="74"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Operations>
+ <Operation name="PrependFile">
+ <Argument>@TargetDir@/C.txt</Argument>
+ <Argument>Prepended text: </Argument>
+ </Operation>
+ </Operations>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/prependfileoperation/prependfileoperation.pro b/tests/auto/installer/prependfileoperation/prependfileoperation.pro
new file mode 100644
index 000000000..5f68385fe
--- /dev/null
+++ b/tests/auto/installer/prependfileoperation/prependfileoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_prependfileoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/prependfileoperation/settings.qrc b/tests/auto/installer/prependfileoperation/settings.qrc
new file mode 100644
index 000000000..deaeb257f
--- /dev/null
+++ b/tests/auto/installer/prependfileoperation/settings.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/B/1.0.2-1content.7z</file>
+ <file>data/repository/B/1.0.2-1meta.7z</file>
+ <file>data/xmloperationrepository/Updates.xml</file>
+ <file>data/xmloperationrepository/C/1.0.0content.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/prependfileoperation/tst_prependfileoperation.cpp b/tests/auto/installer/prependfileoperation/tst_prependfileoperation.cpp
new file mode 100644
index 000000000..12f178cb4
--- /dev/null
+++ b/tests/auto/installer/prependfileoperation/tst_prependfileoperation.cpp
@@ -0,0 +1,180 @@
+/**************************************************************************
+**
+** Copyright (C) 2024 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+
+#include <updateoperations.h>
+#include <packagemanagercore.h>
+
+#include <QFile>
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_prependfileoperation : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase()
+ {
+ m_testFilePath = qApp->applicationDirPath() + QDir::toNativeSeparators("/test");
+ }
+
+ void testMissingArguments()
+ {
+ PrependFileOperation op;
+
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in PrependFile: 0 arguments given, 2 to 4 arguments expected in the form: <filename> <text to prepend> [UNDOOPERATION, \"\"]."));
+
+ op.setArguments(QStringList() << "" << "");
+ QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified");
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError);
+ QCOMPARE(op.errorString(), QString("Cannot open file \"\" for reading: No file name specified"));
+ }
+
+ void testPrependText_data()
+ {
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QString>("prepend");
+ QTest::addColumn<QString>("expected");
+ QTest::addColumn<bool>("overrideUndo");
+ QTest::newRow("newline") << "Line1\nLine2\nLine3\n" << "PrependedText"
+ << "PrependedTextLine1\nLine2\nLine3\n" << false;
+ QTest::newRow("no newline") << "dolore sit amet" << "Lorem ipsum "
+ << "Lorem ipsum dolore sit amet" << false;
+
+ QTest::newRow("no undo")<< "dolore sit amet" << "Lorem ipsum "
+ << "Lorem ipsum dolore sit amet" << true;
+ }
+
+ void testPrependText()
+ {
+ QFETCH(QString, source);
+ QFETCH(QString, prepend);
+ QFETCH(QString, expected);
+ QFETCH(bool, overrideUndo);
+
+ QFile file(m_testFilePath);
+ QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
+
+ QTextStream stream(&file);
+ stream << source << Qt::flush;
+ file.close();
+
+ PrependFileOperation *op = new PrependFileOperation();
+ op->setArguments(QStringList() << m_testFilePath << prepend);
+ if (overrideUndo)
+ op->setArguments(op->arguments() << QLatin1String("UNDOOPERATION"));
+
+ op->backup();
+ QVERIFY(QFileInfo(op->value("backupOfFile").toString()).exists());
+
+ QVERIFY2(op->performOperation(), op->errorString().toLatin1());
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ QCOMPARE(stream.readAll(), expected);
+ file.close();
+
+ QVERIFY2(op->undoOperation(), op->errorString().toLatin1());
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ if (overrideUndo)
+ QCOMPARE(stream.readAll(), expected);
+ else
+ QCOMPARE(stream.readAll(), source);
+ file.close();
+
+ QVERIFY(file.remove());
+
+ QString backupFileName = op->value("backupOfFile").toString();
+ delete op;
+ QVERIFY(!QFileInfo::exists(backupFileName));
+ }
+
+ void testPrependFromCLI_data()
+ {
+ QTest::addColumn<QString>("repository");
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QString>("componentName");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("operationFromScript")
+ << (":///data/repository")
+ << ("B.txt")
+ << ("B")
+ << ("Prepended text: lorem ipsum");
+
+ QTest::newRow("operationFromXML")
+ << (":///data/xmloperationrepository")
+ << ("C.txt")
+ << ("C")
+ << ("Prepended text: lorem ipsum");
+ }
+
+ void testPrependFromCLI()
+ {
+ QFETCH(QString, repository);
+ QFETCH(QString, fileName);
+ QFETCH(QString, componentName);
+ QFETCH(QString, expected);
+
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (installDir, repository));
+ core->installSelectedComponentsSilently(QStringList() << componentName);
+
+ QFile file(installDir + QDir::separator() + fileName);
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ QTextStream stream(&file);
+ QCOMPARE(stream.readAll(), expected);
+ file.close();
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+ // We cannot check the file contents here as it will be deleted on
+ // undo Extract, but at least check that the uninstallation succeeds.
+ QCOMPARE(PackageManagerCore::Success, core->uninstallComponentsSilently
+ (QStringList()<< componentName));
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ }
+
+private:
+ QString m_testFilePath;
+};
+
+QTEST_MAIN(tst_prependfileoperation)
+
+#include "tst_prependfileoperation.moc"
diff --git a/tests/auto/installer/registerfiletypeoperation/data/repository/A/1.0.2-1content.7z b/tests/auto/installer/registerfiletypeoperation/data/repository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..8ba90b13b
--- /dev/null
+++ b/tests/auto/installer/registerfiletypeoperation/data/repository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/registerfiletypeoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/registerfiletypeoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..f3f25d357
--- /dev/null
+++ b/tests/auto/installer/registerfiletypeoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/registerfiletypeoperation/data/repository/Updates.xml b/tests/auto/installer/registerfiletypeoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..6435ae0f7
--- /dev/null
+++ b/tests/auto/installer/registerfiletypeoperation/data/repository/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component for RegisterFileTypeOperation</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6d7a3e15d11a4d94b81452fc2aa18e705a01c922</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/registerfiletypeoperation/registerfiletypeoperation.pro b/tests/auto/installer/registerfiletypeoperation/registerfiletypeoperation.pro
index 0e541ceed..88e366b6d 100644
--- a/tests/auto/installer/registerfiletypeoperation/registerfiletypeoperation.pro
+++ b/tests/auto/installer/registerfiletypeoperation/registerfiletypeoperation.pro
@@ -4,3 +4,7 @@ QT -= gui
QT += testlib network
SOURCES = tst_registerfiletypeoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ..\shared\config.qrc
diff --git a/tests/auto/installer/registerfiletypeoperation/settings.qrc b/tests/auto/installer/registerfiletypeoperation/settings.qrc
new file mode 100644
index 000000000..10cc3c3bb
--- /dev/null
+++ b/tests/auto/installer/registerfiletypeoperation/settings.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1content.7z</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/registerfiletypeoperation/tst_registerfiletypeoperation.cpp b/tests/auto/installer/registerfiletypeoperation/tst_registerfiletypeoperation.cpp
index 7afc372b4..2b2bfc53c 100644
--- a/tests/auto/installer/registerfiletypeoperation/tst_registerfiletypeoperation.cpp
+++ b/tests/auto/installer/registerfiletypeoperation/tst_registerfiletypeoperation.cpp
@@ -1,39 +1,34 @@
/**************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
**************************************************************************/
+#include "../shared/packagemanager.h"
-#include "init.h"
-#include "registerfiletypeoperation.h"
-#include "packagemanagercore.h"
+#include <registerfiletypeoperation.h>
+#include <packagemanagercore.h>
#include <QDir>
#include <QObject>
@@ -41,6 +36,9 @@
#include <QFile>
#include <QTextStream>
#include <QSettings>
+#include <QtGlobal>
+#include <QRandomGenerator>
+
#include "qsettingswrapper.h"
using namespace KDUpdater;
@@ -50,15 +48,40 @@ class tst_registerfiletypeoperation : public QObject
{
Q_OBJECT
+private:
+ void verifySettings()
+ {
+ QCOMPARE(m_settings->value(m_defaultKey).toString(), m_progId);
+ QCOMPARE(m_settings->value(m_openWithProgIdkey).toString(), QString());
+ QCOMPARE(m_settings->value(m_shellKey).toString(), m_command);
+ QCOMPARE(m_settings->value(m_shellAppkey).toString(), m_command);
+ }
+
+ void verifySettingsCleaned()
+ {
+ //Test that values have been removed after undo operation
+ QCOMPARE(m_settings->value(m_defaultKey).toString(), QString());
+ QCOMPARE(m_settings->value(m_openWithProgIdkey).toString(), QString());
+ QCOMPARE(m_settings->value(m_shellKey).toString(), QString());
+ QCOMPARE(m_settings->value(m_shellAppkey).toString(), QString());
+ }
+
+ void clearSettings()
+ {
+ m_settings->setValue(m_defaultKey, QString());
+ m_settings->setValue(m_openWithProgIdkey, QString());
+ m_settings->setValue(m_shellKey, QString());
+ m_settings->setValue(m_shellAppkey, QString());
+ }
+
private slots:
void initTestCase()
{
QInstaller::init();
QString randomString = "";
const QString possible = "abcdefghijklmnopqrstuvwxyz0123456789";
- qsrand(QTime::currentTime().msec());
for (int i = 0; i < 5; i++) {
- int index = qrand() % possible.length();
+ int index = QRandomGenerator::global()->generate() % possible.length();
QChar nextChar = possible.at(index);
randomString.append(nextChar);
@@ -67,7 +90,22 @@ private slots:
m_command = m_core.environmentVariable("SystemRoot") + "\\notepad.exe";
m_progId = "QtProject.QtInstallerFramework." + m_fileType;
+ qputenv("ifw_random_filetype", m_fileType.toUtf8());
+ qputenv("ifw_random_programid", m_progId.toUtf8());
+
+ const QString settingsPath = QString::fromLatin1("HKEY_CURRENT_USER\\Software\\Classes\\");
+ m_settings = new QSettings(settingsPath, QSettings::NativeFormat);
+ m_defaultKey = "." + m_fileType + "/Default";
+ m_openWithProgIdkey = "." + m_fileType + "/OpenWithProgIds/" + m_progId;
+ m_shellKey = m_progId + "/shell/Open/Command/Default/";
+ m_shellAppkey = "/Applications/" + m_progId + "/shell/Open/Command/Default/";
+ }
+ void cleanupTestCase()
+ {
+ qunsetenv("ifw_random_filetype");
+ qunsetenv("ifw_random_programid");
+ delete m_settings;
}
void testMissingArguments()
@@ -87,31 +125,48 @@ private slots:
RegisterFileTypeOperation op(&m_core);
op.setArguments(QStringList() << m_fileType << m_command << "test filetype" <<
"text/plain" << 0 << "ProgId="+m_progId);
-
- const QString settingsPath = QString::fromLatin1("HKEY_CURRENT_USER\\Software\\Classes\\");
- QSettings settings(settingsPath, QSettings::NativeFormat);
-
-
QVERIFY(op.testOperation());
QVERIFY(op.performOperation());
- QString defaultKey = "."+m_fileType+ "/Default";
- QString openWithProgIdkey = "." + m_fileType + "/OpenWithProgIds/" +m_progId;
- QString shellKey = m_progId + "/shell/Open/Command/Default/";
- QString shellAppkey = "/Applications/" + m_progId + "/shell/Open/Command/Default/";
+ verifySettings();
+ QVERIFY(op.undoOperation());
+ verifySettingsCleaned();
+ }
- QCOMPARE(settings.value(defaultKey).toString(), m_progId);
- QCOMPARE(settings.value(openWithProgIdkey).toString(), QString());
- QCOMPARE(settings.value(shellKey).toString(), m_command);
- QCOMPARE(settings.value(shellAppkey).toString(), m_command);
+ void testRegisterFileTypeNoUndo()
+ {
+ RegisterFileTypeOperation op(&m_core);
+ op.setArguments(QStringList() << m_fileType << m_command << "test filetype" <<
+ "text/plain" << 0 << "ProgId="+m_progId << "UNDOOPERATION" << "");
+ QVERIFY(op.testOperation());
+ QVERIFY(op.performOperation());
+ verifySettings();
QVERIFY(op.undoOperation());
+ verifySettings();
- //Test that values have been removed after undo operation
- QCOMPARE(settings.value(defaultKey).toString(), QString());
- QCOMPARE(settings.value(openWithProgIdkey).toString(), QString());
- QCOMPARE(settings.value(shellKey).toString(), QString());
- QCOMPARE(settings.value(shellAppkey).toString(), QString());
+ //Clear so it does not pollute settings
+ clearSettings();
+ }
+
+ void testPerformingFromCLI()
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, ":///data/repository");
+
+ core->installDefaultComponentsSilently();
+ verifySettings();
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ verifySettingsCleaned();
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
}
private:
@@ -119,6 +174,11 @@ private:
QString m_command;
QString m_progId;
PackageManagerCore m_core;
+ QSettings *m_settings;
+ QString m_defaultKey = "."+m_fileType+ "/Default";
+ QString m_openWithProgIdkey = "." + m_fileType + "/OpenWithProgIds/" +m_progId;
+ QString m_shellKey = m_progId + "/shell/Open/Command/Default/";
+ QString m_shellAppkey = "/Applications/" + m_progId + "/shell/Open/Command/Default/";
};
QTEST_MAIN(tst_registerfiletypeoperation)
diff --git a/tests/auto/installer/replaceoperation/data/repository/A/1.0.2-1content.7z b/tests/auto/installer/replaceoperation/data/repository/A/1.0.2-1content.7z
new file mode 100644
index 000000000..8ba90b13b
--- /dev/null
+++ b/tests/auto/installer/replaceoperation/data/repository/A/1.0.2-1content.7z
Binary files differ
diff --git a/tests/auto/installer/replaceoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/replaceoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..b50c31cbd
--- /dev/null
+++ b/tests/auto/installer/replaceoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/replaceoperation/data/repository/Updates.xml b/tests/auto/installer/replaceoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..7585b57a4
--- /dev/null
+++ b/tests/auto/installer/replaceoperation/data/repository/Updates.xml
@@ -0,0 +1,17 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>edb7672270729f9d34396cb70e6afd12fec90d2b</SHA1>
+ <UpdateFile CompressedSize="225" UncompressedSize="75" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/replaceoperation/replaceoperation.pro b/tests/auto/installer/replaceoperation/replaceoperation.pro
index d2756d153..2334fd661 100644
--- a/tests/auto/installer/replaceoperation/replaceoperation.pro
+++ b/tests/auto/installer/replaceoperation/replaceoperation.pro
@@ -4,3 +4,7 @@ QT -= gui
QT += testlib
SOURCES += tst_replaceoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/replaceoperation/settings.qrc b/tests/auto/installer/replaceoperation/settings.qrc
new file mode 100644
index 000000000..10cc3c3bb
--- /dev/null
+++ b/tests/auto/installer/replaceoperation/settings.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1content.7z</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/replaceoperation/tst_replaceoperation.cpp b/tests/auto/installer/replaceoperation/tst_replaceoperation.cpp
index 9afd91875..488a14dd1 100644
--- a/tests/auto/installer/replaceoperation/tst_replaceoperation.cpp
+++ b/tests/auto/installer/replaceoperation/tst_replaceoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -25,15 +25,16 @@
** $QT_END_LICENSE$
**
**************************************************************************/
+#include "../shared/packagemanager.h"
#include <fileutils.h>
#include <replaceoperation.h>
-#include <qinstallerglobal.h>
+#include <packagemanagercore.h>
-#include <QObject>
#include <QDir>
#include <QFile>
#include <QTest>
+#include <QRandomGenerator>
using namespace KDUpdater;
using namespace QInstaller;
@@ -46,7 +47,7 @@ private slots:
void initTestCase()
{
m_testDirectory = QInstaller::generateTemporaryFileName();
- m_testFilePath = m_testDirectory + "/test." + QString::number(qrand() % 1000);
+ m_testFilePath = m_testDirectory + "/test." + QString::number(QRandomGenerator::global()->generate() % 1000);
}
void testWrongArguments()
@@ -102,7 +103,7 @@ private slots:
QTextStream stream(&file);
stream << "Lorem ipsum dolore sit amet, consectetur adipiscing elit, sed do eiusmod "
- "tempor incididunt ut labore et dolore magna aliqua." << endl;
+ "tempor incididunt ut labore et dolore magna aliqua." << Qt::endl;
file.close();
ReplaceOperation searchReplaceOperation(nullptr);
@@ -138,7 +139,7 @@ private slots:
QTextStream stream(&file);
stream << "one | 10/10/2010 | three | 1.2345 | 0.00001 "
- "| 7 | A <i>bon mot</i>." << endl;
+ "| 7 | A <i>bon mot</i>." << Qt::endl;
file.close();
ReplaceOperation searchReplaceOperation(nullptr);
@@ -174,6 +175,25 @@ private slots:
QVERIFY(QDir().rmdir(m_testDirectory));
}
+ void testPerformingFromCLI()
+ {
+ QVERIFY(QDir().mkpath(m_testDirectory));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (m_testDirectory, ":///data/repository");
+
+ core->installDefaultComponentsSilently();
+
+ QFile file(m_testDirectory + QDir::separator() + "A.txt");
+ QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
+ QTextStream stream(&file);
+ QCOMPARE(stream.readLine(), QLatin1String("text to replace."));
+ QCOMPARE(stream.readLine(), QLatin1String("Another text."));
+ file.close();
+ QDir dir(m_testDirectory);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
private:
QString m_testDirectory;
QString m_testFilePath;
diff --git a/tests/auto/installer/repository/data/compressedRepository/compressedRepository.7z b/tests/auto/installer/repository/data/compressedRepository/compressedRepository.7z
new file mode 100644
index 000000000..335685bb0
--- /dev/null
+++ b/tests/auto/installer/repository/data/compressedRepository/compressedRepository.7z
Binary files differ
diff --git a/tests/auto/installer/repository/data/repository/A/1.0.2content.7z b/tests/auto/installer/repository/data/repository/A/1.0.2content.7z
new file mode 100644
index 000000000..5531e9072
--- /dev/null
+++ b/tests/auto/installer/repository/data/repository/A/1.0.2content.7z
Binary files differ
diff --git a/tests/auto/installer/repository/data/repository/A/1.0.2meta.7z b/tests/auto/installer/repository/data/repository/A/1.0.2meta.7z
new file mode 100644
index 000000000..6631280a7
--- /dev/null
+++ b/tests/auto/installer/repository/data/repository/A/1.0.2meta.7z
Binary files differ
diff --git a/tests/auto/installer/repository/data/repository/B/1.0.0meta.7z b/tests/auto/installer/repository/data/repository/B/1.0.0meta.7z
new file mode 100644
index 000000000..16f3a6c42
--- /dev/null
+++ b/tests/auto/installer/repository/data/repository/B/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/repository/data/repository/C/1.0.0meta.7z b/tests/auto/installer/repository/data/repository/C/1.0.0meta.7z
new file mode 100644
index 000000000..37c8fffc4
--- /dev/null
+++ b/tests/auto/installer/repository/data/repository/C/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/repository/data/repository/Updates.xml b/tests/auto/installer/repository/data/repository/Updates.xml
new file mode 100644
index 000000000..f541882c5
--- /dev/null
+++ b/tests/auto/installer/repository/data/repository/Updates.xml
@@ -0,0 +1,33 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <Script postLoad="true">script.qs</Script>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ <Script>script.qs</Script>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ <Script postLoad="false">script.qs</Script>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/repository/repository.pro b/tests/auto/installer/repository/repository.pro
index 2d192eeaa..7603177b1 100644
--- a/tests/auto/installer/repository/repository.pro
+++ b/tests/auto/installer/repository/repository.pro
@@ -4,3 +4,7 @@ QT += network
QT -= gui
SOURCES += tst_repository.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/repository/settings.qrc b/tests/auto/installer/repository/settings.qrc
new file mode 100644
index 000000000..92db7e3e1
--- /dev/null
+++ b/tests/auto/installer/repository/settings.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2content.7z</file>
+ <file>data/repository/A/1.0.2meta.7z</file>
+ <file>data/repository/B/1.0.0meta.7z</file>
+ <file>data/repository/C/1.0.0meta.7z</file>
+ <file>data/compressedRepository/compressedRepository.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/repository/tst_repository.cpp b/tests/auto/installer/repository/tst_repository.cpp
index 7b8405baf..112098130 100644
--- a/tests/auto/installer/repository/tst_repository.cpp
+++ b/tests/auto/installer/repository/tst_repository.cpp
@@ -1,3 +1,34 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
#include "repository.h"
#include "repositorycategory.h"
#include "settings.h"
@@ -8,6 +39,8 @@
using namespace QInstaller;
+typedef QList<QPair<QString, QString>> SettingsPairList;
+
class tst_Repository : public QObject
{
Q_OBJECT
@@ -137,7 +170,7 @@ private slots:
categories.insert(category);
settings.setRepositoryCategories(categories);
- QHash<QString, QPair<Repository, Repository>> update;
+ QMultiHash<QString, QPair<Repository, Repository>> update;
// non-empty update
update.insert(QLatin1String("replace"), qMakePair(original, replacement));
@@ -161,6 +194,120 @@ private slots:
update.insert(QLatin1String("replace"), qMakePair(nonMatching, replacement));
QVERIFY(settings.updateRepositoryCategories(update) == Settings::NoUpdatesApplied);
}
+
+ void testCompressedRepositoryWithPriority()
+ {
+ // Compressed repository has higher priority than normal repository.
+ // If the versions match, compressed repository is used instead of normal repository.
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit(installDir, ":///data/repository");
+ core->setTemporaryRepositories(QStringList()
+ << ":///data/compressedRepository/compressedRepository.7z", false, true);
+ core->installSelectedComponentsSilently(QStringList() << "A");
+ VerifyInstaller::verifyFileExistence(installDir, QStringList() << "components.xml" << "A_from_compressed.txt");
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
+ void testPostLoadScriptFromRepository_data()
+ {
+ QTest::addColumn<QStringList>("installComponent");
+ QTest::addColumn<bool>("repositoryPostLoadSetting");
+ QTest::addColumn<SettingsPairList>("expectedSettingsBeforeInstall");
+ QTest::addColumn<SettingsPairList>("expectedSettingsAfterInstall");
+ QTest::addColumn<QStringList>("unexpectedSettings");
+
+ // component A has postLoad = true in component.xml
+ // component B has no postLoad attribute
+ // component C has postLoad = false in component.xml
+
+ SettingsPairList expectedSettingsListAfterInstall;
+ expectedSettingsListAfterInstall.append(QPair<QString, QString>("componentAKey", "componentAValue"));
+
+ SettingsPairList expectedSettingsListBeforeInstall;
+ expectedSettingsListBeforeInstall.append(QPair<QString, QString>("componentBKey", "componentBValue"));
+ expectedSettingsListBeforeInstall.append(QPair<QString, QString>("componentCKey", "componentCValue"));
+
+ QTest::newRow("noRepoPostLoadComponentA")
+ << (QStringList() << "A")
+ << false
+ << expectedSettingsListBeforeInstall
+ << expectedSettingsListAfterInstall
+ << (QStringList());
+
+ // Component B is installed so values from component A and component C should not be set
+ expectedSettingsListAfterInstall.clear();
+ expectedSettingsListAfterInstall.append(QPair<QString, QString>("componentBKey", "componentBValue"));
+ QTest::newRow("noRepoPostLoadComponentB")
+ << (QStringList() << "B")
+ << false
+ << expectedSettingsListBeforeInstall
+ << expectedSettingsListAfterInstall
+ << (QStringList() << "componentAValue" << "componentCValue");
+
+ // PostLoad is set to whole repository. Since only A is installed,
+ // values from component B and component C values are not set
+ expectedSettingsListBeforeInstall.clear();
+ expectedSettingsListAfterInstall.clear();
+ expectedSettingsListAfterInstall.append(QPair<QString, QString>("componentAKey", "componentAValue"));
+ QTest::newRow("repoPostLoadComponentA") << (QStringList() << "A")
+ << true
+ << expectedSettingsListBeforeInstall
+ << expectedSettingsListAfterInstall
+ << (QStringList() << "componentBValue" << "componentCValue");
+
+ // PostLoad is set to whole repository. Since only B is installed,
+ // values from component C and component A are not set.
+ expectedSettingsListAfterInstall.clear();
+ expectedSettingsListAfterInstall.append(QPair<QString, QString>("componentBKey", "componentBValue"));
+ QTest::newRow("repoPostLoadComponentB") << (QStringList() << "B")
+ << true
+ << expectedSettingsListBeforeInstall
+ << expectedSettingsListAfterInstall
+ << (QStringList() << "componentCValue" << "componentAValue");
+
+ // PostLoad is set to whole repository. Since component C has its postload = false,
+ // value is set to component C before install
+ expectedSettingsListBeforeInstall.clear();
+ expectedSettingsListAfterInstall.clear();
+ expectedSettingsListBeforeInstall.append(QPair<QString, QString>("componentCKey", "componentCValue"));
+ QTest::newRow("repoPostLoadComponentC") << (QStringList() << "C")
+ << true
+ << expectedSettingsListBeforeInstall
+ << expectedSettingsListAfterInstall
+ << (QStringList() << "componentAValue" << "componentBValue");
+ }
+
+ void testPostLoadScriptFromRepository()
+ {
+ QFETCH(QStringList, installComponent);
+ QFETCH(bool, repositoryPostLoadSetting);
+ QFETCH(SettingsPairList, expectedSettingsBeforeInstall);
+ QFETCH(SettingsPairList, expectedSettingsAfterInstall);
+ QFETCH(QStringList, unexpectedSettings);
+
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit(installDir));
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(":///data/repository");
+ repo.setPostLoadComponentScript(repositoryPostLoadSetting);
+ repoList.insert(repo);
+ core->settings().setDefaultRepositories(repoList);
+ QVERIFY(core->fetchRemotePackagesTree());
+
+ for (const QPair<QString, QString> settingValue : expectedSettingsBeforeInstall)
+ QCOMPARE(core->value(settingValue.first), settingValue.second);
+
+ core->installSelectedComponentsSilently(installComponent);
+ for (const QPair<QString, QString> settingValue : expectedSettingsAfterInstall)
+ QCOMPARE(core->value(settingValue.first), settingValue.second);
+ for (const QString unexpectedSetting : unexpectedSettings)
+ QVERIFY2(!core->containsValue(unexpectedSetting), "Core contains unexpected value");
+ }
};
QTEST_MAIN(tst_Repository)
diff --git a/tests/auto/installer/rmdiroperationtest/rmdiroperationtest.pro b/tests/auto/installer/rmdiroperationtest/rmdiroperationtest.pro
new file mode 100644
index 000000000..72e61ad80
--- /dev/null
+++ b/tests/auto/installer/rmdiroperationtest/rmdiroperationtest.pro
@@ -0,0 +1,6 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_rmdiroperationtest.cpp
diff --git a/tests/auto/installer/rmdiroperationtest/tst_rmdiroperationtest.cpp b/tests/auto/installer/rmdiroperationtest/tst_rmdiroperationtest.cpp
new file mode 100644
index 000000000..bfdd5921e
--- /dev/null
+++ b/tests/auto/installer/rmdiroperationtest/tst_rmdiroperationtest.cpp
@@ -0,0 +1,111 @@
+/**************************************************************************
+**
+** Copyright (C) 2024 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#include "init.h"
+#include "updateoperations.h"
+
+#include <QDir>
+#include <QObject>
+#include <QTest>
+#include <QFile>
+#include <QTextStream>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_rmdiroperationtest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase()
+ {
+ QInstaller::init();
+ QString path = QDir::current().path() + QDir::toNativeSeparators("/test");
+ if (QDir(path).exists()) {
+ QFAIL("Remove test folder first!");
+ }
+ }
+
+ void testMissingArguments()
+ {
+ RmdirOperation op;
+
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QLatin1String("Invalid arguments in Rmdir: 0 arguments given, 1 to 3 "
+ "arguments expected in the form: <file to remove> [UNDOOPERATION, \"\"]."));
+ }
+
+ void testRemoveDirectory_data()
+ {
+ QTest::addColumn<QString>("directory");
+ QTest::addColumn<bool>("overrideUndo");
+ QTest::newRow("/test") << "/test" << false;
+ QTest::newRow("/test/test") << "/test/test" << false;
+ QTest::newRow("/test/test/test") << "/test/test/test" << false;
+ QTest::newRow("no undo") << "/test/test/test/test" << true;
+ }
+
+ void testRemoveDirectory()
+ {
+ QFETCH(QString, directory);
+ QFETCH(bool, overrideUndo);
+
+ QString path = QDir::current().path() + QDir::toNativeSeparators(directory);
+ //Create first the directories utilizing MkdirOperation
+ MkdirOperation op;
+ op.setArguments(QStringList() << path);
+ op.setArguments(op.arguments() << QLatin1String("UNDOOPERATION"));
+ op.backup();
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY2(QDir(path).exists(), path.toLatin1());
+
+ RmdirOperation rmOp;
+ rmOp.setArguments(QStringList() << path);
+ if (overrideUndo)
+ rmOp.setArguments(op.arguments() << QLatin1String("UNDOOPERATION"));
+ rmOp.backup();
+ rmOp.performOperation();
+ QVERIFY2(!QDir(path).exists(), path.toLatin1());
+
+ QVERIFY2(rmOp.undoOperation(), rmOp.errorString().toLatin1());
+ if (overrideUndo) {
+ QVERIFY2(!QDir(path).exists(), path.toLatin1());
+ } else {
+ QVERIFY2(QDir(path).exists(), path.toLatin1());
+ QVERIFY(QDir(path).removeRecursively());
+ }
+ }
+};
+
+QTEST_MAIN(tst_rmdiroperationtest)
+
+#include "tst_rmdiroperationtest.moc"
diff --git a/tests/auto/installer/scriptengine/data/addOperation.qs b/tests/auto/installer/scriptengine/data/addOperation.qs
index d7d505a6b..e4a85a730 100644
--- a/tests/auto/installer/scriptengine/data/addOperation.qs
+++ b/tests/auto/installer/scriptengine/data/addOperation.qs
@@ -1,31 +1,26 @@
/**************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
diff --git a/tests/auto/installer/scriptengine/data/auto-install.qs b/tests/auto/installer/scriptengine/data/auto-install.qs
index 6decd31dc..4b0d28b14 100644
--- a/tests/auto/installer/scriptengine/data/auto-install.qs
+++ b/tests/auto/installer/scriptengine/data/auto-install.qs
@@ -50,3 +50,5 @@ Controller.prototype.FinishedPageCallback = function()
{
print("FinishedPageCallback - OK")
}
+
+// Trailing comment to exercise QTIFW-1062 \ No newline at end of file
diff --git a/tests/auto/installer/scriptengine/tst_scriptengine.cpp b/tests/auto/installer/scriptengine/tst_scriptengine.cpp
index b7c602e26..86017a229 100644
--- a/tests/auto/installer/scriptengine/tst_scriptengine.cpp
+++ b/tests/auto/installer/scriptengine/tst_scriptengine.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -221,13 +221,6 @@ private slots:
.hasProperty(QLatin1String("getExistingDirectory")), true);
QCOMPARE(global.property(QLatin1String("QFileDialog"))
.hasProperty(QLatin1String("getOpenFileName")), true);
-
- QCOMPARE(global.hasProperty(QLatin1String("InstallerProxy")), true);
- QCOMPARE(global.property(QLatin1String("InstallerProxy"))
- .hasProperty(QLatin1String("componentByName")), true);
- QCOMPARE(global.property(QLatin1String("InstallerProxy"))
- .hasProperty(QLatin1String("components")), true);
-
QCOMPARE(global.hasProperty(QLatin1String("QDesktopServices")), true);
QCOMPARE(global.property(QLatin1String("QDesktopServices"))
.hasProperty(QLatin1String("openUrl")), true);
@@ -249,6 +242,8 @@ private slots:
QJSValue sinfo = global.property(QLatin1String("systemInfo"));
QCOMPARE(sinfo.property(QLatin1String("currentCpuArchitecture")).toString(),
QSysInfo::currentCpuArchitecture());
+ QCOMPARE(sinfo.property(QLatin1String("buildCpuArchitecture")).toString(),
+ QSysInfo::buildCpuArchitecture());
QCOMPARE(sinfo.property(QLatin1String("kernelType")).toString(), QSysInfo::kernelType());
QCOMPARE(sinfo.property(QLatin1String("kernelVersion")).toString(),
QSysInfo::kernelVersion());
@@ -349,6 +344,21 @@ private slots:
}
}
+ void testComponentsWithRegexp()
+ {
+ const QString script = QString::fromLatin1("var components = installer.components(\"component.test.addOperation\");"
+ "\n"
+ "for (i = 0; i < components.length; i++)"
+ "print(components[i].name);");
+
+ setExpectedScriptOutput("component.test.addOperation");
+ const QJSValue value = m_scriptEngine->evaluate(script);
+ if (value.isError()) {
+ QFAIL(qPrintable(QString::fromLatin1("ScriptEngine error:\n %1").arg(
+ value.toString())));
+ }
+ }
+
void testFindFiles()
{
const QString expectedOutput = QString::fromLatin1("Found file %1/tst_scriptengine.moc").arg(m_applicatonDirPath);
@@ -373,13 +383,24 @@ private slots:
QCOMPARE(result.isError(), false);
}
+ void loadSimpleComponentScript_data()
+ {
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("postLoad");
+ QTest::newRow("Pre component script") << ":///data/component1.qs" << false;
+ QTest::newRow("Post component script") << ":///data/component1.qs" << true;
+ }
+
void loadSimpleComponentScript()
{
- try {
- // ignore retranslateUi which is called by loadComponentScript
+ QFETCH(QString, path);
+ QFETCH(bool, postLoad);
+
+ try {
+ // ignore retranslateUi which is called by evaluateComponentScript
setExpectedScriptOutput("Component constructor - OK");
setExpectedScriptOutput("retranslateUi - OK");
- m_component->loadComponentScript(":///data/component1.qs");
+ m_component->evaluateComponentScript(path, postLoad);
setExpectedScriptOutput("retranslateUi - OK");
m_component->languageChanged();
@@ -407,8 +428,19 @@ private slots:
}
}
+ void loadBrokenComponentScript_data()
+ {
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("postLoad");
+ QTest::newRow("Pre component script") << ":///data/component2.qs" << false;
+ QTest::newRow("Post component script") << ":///data/component2.qs" << true;
+ }
+
void loadBrokenComponentScript()
{
+ QFETCH(QString, path);
+ QFETCH(bool, postLoad);
+
Component *testComponent = new Component(&m_core);
testComponent->setValue(scName, "broken.component");
@@ -418,21 +450,32 @@ private slots:
try {
// ignore Output from script
setExpectedScriptOutput("script function: Component");
- testComponent->loadComponentScript(":///data/component2.qs");
+ testComponent->evaluateComponentScript(path, postLoad);
} catch (const Error &error) {
const QString debugMessage(
- QString("create Error-Exception: \"Exception while loading the component script \"%1\": "
- "ReferenceError: broken is not defined\"").arg(QDir::toNativeSeparators(":///data/component2.qs")));
+ QString("Exception while loading the component script \"%1\": "
+ "ReferenceError: broken is not defined on line number: 33").arg(QDir::toNativeSeparators(":///data/component2.qs")));
QVERIFY2(debugMessage.contains(error.message()), "(ReferenceError: broken is not defined)");
}
}
+ void loadComponentUserInterfaces_data()
+ {
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("postLoad");
+ QTest::newRow("Pre component script") << ":///data/userinterface.qs" << false;
+ QTest::newRow("Post component script") << ":///data/userinterface.qs" << true;
+ }
+
void loadComponentUserInterfaces()
{
- try {
+ QFETCH(QString, path);
+ QFETCH(bool, postLoad);
+ try {
setExpectedScriptOutput("checked: false");
+ TestGui testGui(&m_core);
m_component->loadUserInterfaces(QDir(":///data"), QStringList() << QLatin1String("form.ui"));
- m_component->loadComponentScript(":///data/userinterface.qs");
+ m_component->evaluateComponentScript(path, postLoad);
} catch (const Error &error) {
QFAIL(qPrintable(error.message()));
}
@@ -576,7 +619,7 @@ private slots:
try {
m_core.setPackageManager();
Component *component = m_core.componentByName("component.test.addOperation");
- component->loadComponentScript(":///data/addOperation.qs");
+ component->evaluateComponentScript(":///data/addOperation.qs");
setExpectedScriptOutput("Component::createOperations()");
component->createOperations();
diff --git a/tests/auto/installer/settings/data/full_config.xml b/tests/auto/installer/settings/data/full_config.xml
index 272a1b0d7..bccb6f7ca 100644
--- a/tests/auto/installer/settings/data/full_config.xml
+++ b/tests/auto/installer/settings/data/full_config.xml
@@ -37,7 +37,9 @@ File should contain all elements we allow in a config.xml
<DependsOnLocalInstallerBinary>true</DependsOnLocalInstallerBinary>
<AllowSpaceInPath>true</AllowSpaceInPath>
<AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>
+ <AllowRepositoriesForOfflineInstaller>true</AllowRepositoriesForOfflineInstaller>
<DisableAuthorizationFallback>true</DisableAuthorizationFallback>
+ <DisableCommandLineInterface>true</DisableCommandLineInterface>
<RepositorySettingsPageVisible>false</RepositorySettingsPageVisible>
<CreateLocalRepository>false</CreateLocalRepository>
<TargetConfigurationFile>components.xml</TargetConfigurationFile>
diff --git a/tests/auto/installer/settings/data/length_units_invalid.xml b/tests/auto/installer/settings/data/length_units_invalid.xml
index b1dc5aa62..7c5e99dd0 100644
--- a/tests/auto/installer/settings/data/length_units_invalid.xml
+++ b/tests/auto/installer/settings/data/length_units_invalid.xml
@@ -4,4 +4,6 @@
<Version>1.2.3</Version>
<WizardDefaultWidth>800pt</WizardDefaultWidth>
<WizardDefaultHeight>600pt</WizardDefaultHeight>
+ <WizardMinimumWidth>640pt</WizardMinimumWidth>
+ <WizardMinimumHeight>480pt</WizardMinimumHeight>
</Installer>
diff --git a/tests/auto/installer/settings/data/length_units_valid_em.xml b/tests/auto/installer/settings/data/length_units_valid_em.xml
index af087fdfe..81eec5af7 100644
--- a/tests/auto/installer/settings/data/length_units_valid_em.xml
+++ b/tests/auto/installer/settings/data/length_units_valid_em.xml
@@ -4,4 +4,6 @@
<Version>1.2.3</Version>
<WizardDefaultWidth>800em</WizardDefaultWidth>
<WizardDefaultHeight>600em</WizardDefaultHeight>
+ <WizardMinimumWidth>640em</WizardMinimumWidth>
+ <WizardMinimumHeight>480em</WizardMinimumHeight>
</Installer>
diff --git a/tests/auto/installer/settings/data/length_units_valid_ex.xml b/tests/auto/installer/settings/data/length_units_valid_ex.xml
index 3b39cf7a7..633a239ef 100644
--- a/tests/auto/installer/settings/data/length_units_valid_ex.xml
+++ b/tests/auto/installer/settings/data/length_units_valid_ex.xml
@@ -4,4 +4,6 @@
<Version>1.2.3</Version>
<WizardDefaultWidth>800ex</WizardDefaultWidth>
<WizardDefaultHeight>600ex</WizardDefaultHeight>
+ <WizardMinimumWidth>640ex</WizardMinimumWidth>
+ <WizardMinimumHeight>480ex</WizardMinimumHeight>
</Installer>
diff --git a/tests/auto/installer/settings/data/length_units_valid_px.xml b/tests/auto/installer/settings/data/length_units_valid_px.xml
index 3553dd7d8..71518a71c 100644
--- a/tests/auto/installer/settings/data/length_units_valid_px.xml
+++ b/tests/auto/installer/settings/data/length_units_valid_px.xml
@@ -4,4 +4,6 @@
<Version>1.2.3</Version>
<WizardDefaultWidth>800px</WizardDefaultWidth>
<WizardDefaultHeight>600px</WizardDefaultHeight>
+ <WizardMinimumWidth>640px</WizardMinimumWidth>
+ <WizardMinimumHeight>480px</WizardMinimumHeight>
</Installer>
diff --git a/tests/auto/installer/settings/tst_settings.cpp b/tests/auto/installer/settings/tst_settings.cpp
index ab8611e12..15dcc98a1 100644
--- a/tests/auto/installer/settings/tst_settings.cpp
+++ b/tests/auto/installer/settings/tst_settings.cpp
@@ -1,3 +1,31 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
#include "settings.h"
#include "errors.h"
#include "repository.h"
@@ -8,6 +36,8 @@
using namespace QInstaller;
+typedef QMap<QString, QVariant> ProductImageMap;
+
class tst_Settings : public QObject
{
Q_OBJECT
@@ -45,6 +75,7 @@ void tst_Settings::loadTutorialConfig()
QCOMPARE(settings.watermark(), QString());
QCOMPARE(settings.banner(), QString());
QCOMPARE(settings.background(), QString());
+ QCOMPARE(settings.pageListPixmap(), QString());
#if defined(Q_OS_WIN)
QCOMPARE(settings.installerApplicationIcon(), QLatin1String(":/installer.ico"));
QCOMPARE(settings.installerWindowIcon(), QLatin1String(":/installer.ico"));
@@ -59,8 +90,12 @@ void tst_Settings::loadTutorialConfig()
QCOMPARE(settings.systemIconSuffix(), QLatin1String(".png"));
#endif
QCOMPARE(settings.wizardStyle(), QString());
- QCOMPARE(settings.wizardDefaultWidth(), 0);
+ QCOMPARE(settings.wizardDefaultWidth(), settings.wizardShowPageList() ? 800 : 0);
QCOMPARE(settings.wizardDefaultHeight(), 0);
+ QCOMPARE(settings.wizardMinimumWidth(), 0);
+ QCOMPARE(settings.wizardMinimumHeight(), 0);
+ QCOMPARE(settings.wizardShowPageList(), true);
+ QCOMPARE(settings.productImages(), ProductImageMap());
QCOMPARE(settings.titleColor(), QString());
QCOMPARE(settings.runProgram(), QString());
QCOMPARE(settings.runProgramArguments(), QStringList());
@@ -74,7 +109,9 @@ void tst_Settings::loadTutorialConfig()
QCOMPARE(settings.repositorySettingsPageVisible(), true);
QCOMPARE(settings.allowSpaceInPath(), true);
QCOMPARE(settings.allowNonAsciiCharacters(), false);
+ QCOMPARE(settings.allowRepositoriesForOfflineInstaller(), true);
QCOMPARE(settings.disableAuthorizationFallback(), false);
+ QCOMPARE(settings.disableCommandLineInterface(), false);
QCOMPARE(settings.createLocalRepository(), false);
QCOMPARE(settings.installActionColumnVisible(), false);
@@ -212,6 +249,8 @@ void tst_Settings::loadConfigWithValidLengthUnits()
Settings settings = Settings::fromFileAndPrefix(":///data/length_units_valid_px.xml", ":///data");
QCOMPARE(settings.wizardDefaultWidth(), 800);
QCOMPARE(settings.wizardDefaultHeight(), 600);
+ QCOMPARE(settings.wizardMinimumWidth(), 640);
+ QCOMPARE(settings.wizardMinimumHeight(), 480);
// Cannot test the parsed values for these units portably since the
// pixel value depends on the font metrics. Let's just check for parse
@@ -229,6 +268,8 @@ void tst_Settings::loadConfigWithInvalidLengthUnits()
Settings settings = Settings::fromFileAndPrefix(":///data/length_units_invalid.xml", ":///data");
QCOMPARE(settings.wizardDefaultWidth(), 0);
QCOMPARE(settings.wizardDefaultHeight(), 0);
+ QCOMPARE(settings.wizardMinimumWidth(), 0);
+ QCOMPARE(settings.wizardMinimumHeight(), 0);
} catch (const Error &error) {
QFAIL(qPrintable(QString::fromLatin1("Exception caught: %1").arg(error.message())));
}
diff --git a/tests/auto/installer/settingsoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/settingsoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..b283108bb
--- /dev/null
+++ b/tests/auto/installer/settingsoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/settingsoperation/data/repository/B/1.0.0meta.7z b/tests/auto/installer/settingsoperation/data/repository/B/1.0.0meta.7z
new file mode 100644
index 000000000..211bc0e0a
--- /dev/null
+++ b/tests/auto/installer/settingsoperation/data/repository/B/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/settingsoperation/data/repository/C/1.0.0meta.7z b/tests/auto/installer/settingsoperation/data/repository/C/1.0.0meta.7z
new file mode 100644
index 000000000..a990fdbf1
--- /dev/null
+++ b/tests/auto/installer/settingsoperation/data/repository/C/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/settingsoperation/data/repository/Updates.xml b/tests/auto/installer/settingsoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..3e88f849d
--- /dev/null
+++ b/tests/auto/installer/settingsoperation/data/repository/Updates.xml
@@ -0,0 +1,33 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ <Script>script.qs</Script>
+ <SHA1>5dc8a98f591998de0c555e194e228fa740a15632</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>B</Name>
+ <DisplayName>B</DisplayName>
+ <Description>Example component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ <Script>script.qs</Script>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>C</Name>
+ <DisplayName>C</DisplayName>
+ <Description>Example component C</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>false</Default>
+ <Script>script.qs</Script>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/settingsoperation/settings.qrc b/tests/auto/installer/settingsoperation/settings.qrc
new file mode 100644
index 000000000..8da639ad6
--- /dev/null
+++ b/tests/auto/installer/settingsoperation/settings.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ <file>data/repository/B/1.0.0meta.7z</file>
+ <file>data/repository/C/1.0.0meta.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/settingsoperation/settingsoperation.pro b/tests/auto/installer/settingsoperation/settingsoperation.pro
index 60ddd329b..b4233f53f 100644
--- a/tests/auto/installer/settingsoperation/settingsoperation.pro
+++ b/tests/auto/installer/settingsoperation/settingsoperation.pro
@@ -4,3 +4,6 @@ QT -= gui
QT += testlib
SOURCES += tst_settingsoperation.cpp
+
+RESOURCES += settings.qrc\
+ ../shared/config.qrc
diff --git a/tests/auto/installer/settingsoperation/tst_settingsoperation.cpp b/tests/auto/installer/settingsoperation/tst_settingsoperation.cpp
index ced0e6f36..2da0870c7 100644
--- a/tests/auto/installer/settingsoperation/tst_settingsoperation.cpp
+++ b/tests/auto/installer/settingsoperation/tst_settingsoperation.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -25,14 +25,15 @@
** $QT_END_LICENSE$
**
**************************************************************************/
+
+#include "../shared/packagemanager.h"
#include <utils.h>
#include <settingsoperation.h>
-#include <qinstallerglobal.h>
+#include <packagemanagercore.h>
+#include <settings.h>
-#include <QObject>
#include <QTest>
#include <QSettings>
-#include <QDir>
using namespace KDUpdater;
using namespace QInstaller;
@@ -89,7 +90,7 @@ private slots:
UpdateOperation::InvalidArguments);
compareString = "Current method argument calling \"Settings\" with arguments \"path=first; "
"method=second; key=third; value=fourth\" is not supported. Please use set, remove, "
- "add_array_value or remove_array_value.";
+ "add_array_value, or remove_array_value.";
QCOMPARE(wrongMethodArgumentOperation.errorString(), compareString);
// same for undo
@@ -176,6 +177,7 @@ private slots:
QFile testFile(testFilePath);
QVERIFY2(testFile.open(QIODevice::WriteOnly | QIODevice::Text), contentFile.errorString().toLatin1());
+ m_cleanupFilePaths << testFilePath;
QTextStream out(&testFile);
@@ -243,6 +245,7 @@ private slots:
QFile testFile(testFilePath);
QVERIFY2(testFile.open(QIODevice::WriteOnly | QIODevice::Text), contentFile.errorString()
.toLatin1());
+ m_cleanupFilePaths << testFilePath;
QTextStream out(&testFile);
@@ -280,6 +283,96 @@ private slots:
}
}
+ void testPerformingFromCLI()
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, ":///data/repository");
+
+ QSettings testSettings(QDir(m_testSettingsDirPath).filePath(m_testSettingsFilename),
+ QSettings::IniFormat);
+ QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(),
+ QStringList() << "value1" << "value2" << "value3");
+
+ core->installSelectedComponentsSilently(QStringList() << "A");
+
+ QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(),
+ QStringList() << "value1" << "value2" << "value3" << "valueFromScript");
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ core->uninstallComponentsSilently(QStringList() << "A");
+
+ QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(),
+ QStringList() << "value1" << "value2" << "value3");
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
+ void testPerformingFromCLIWithPlaceholders()
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, ":///data/repository");
+
+ core->installSelectedComponentsSilently(QStringList() << "B");
+ // Path is set in component constructor in install script
+ const QString settingsFile = core->value("SettingsPathFromVariable");
+ QSettings testSettings(QDir(m_testSettingsDirPath).filePath(settingsFile),
+ QSettings::IniFormat);
+
+ QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(),
+ QStringList() << "ValueFromPlaceholder");
+
+ core->commitSessionOperations();
+ core->setPackageManager();
+ core->uninstallComponentsSilently(QStringList() << "B");
+
+ // Settings file is removed as it is empty
+ QVERIFY(!QFile::exists(settingsFile));
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
+ void testPerformingFromCLIWithSettingsFileMoved()
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, ":///data/repository");
+
+
+ core->installSelectedComponentsSilently(QStringList() << "C");
+
+ const QString settingsFileName = qApp->applicationDirPath() + "/oldTestSettings.ini";
+ QSettings testSettings(QDir(m_testSettingsDirPath).filePath(settingsFileName),
+ QSettings::IniFormat);
+
+ QCOMPARE(testSettings.value("testcategory/categoryarrayvalue1").toStringList(),
+ QStringList() << "valueFromScript");
+
+ QFile settingsFile(settingsFileName);
+ // Move the settings path to new location. Script has set values
+ // ComponentCSettingsPath (@InstallerDirPath@/newTestSettings.ini) and
+ // ComponentCSettingsPath_OLD (@InstallerDirPath@/oldTestSettings.ini) so
+ // UNDO operation should delete the moved newTestSettings.ini file instead.
+ QVERIFY2(settingsFile.rename(qApp->applicationDirPath() + "/newTestSettings.ini"), "Could not move settings file.");
+ core->commitSessionOperations();
+ core->setPackageManager();
+ core->uninstallComponentsSilently(QStringList() << "C");
+
+ // Settings file is removed in uninstall as it is empty
+ QVERIFY2(!QFile::exists(qApp->applicationDirPath() + "/newTestSettings.ini"), "Settings file not deleted correctly");
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+
// called after all tests
void cleanupTestCase()
{
diff --git a/tests/auto/installer/shared/config.qrc b/tests/auto/installer/shared/config.qrc
new file mode 100644
index 000000000..b25a589a3
--- /dev/null
+++ b/tests/auto/installer/shared/config.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/metadata">
+ <file>installer-config/config.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/shared/installer-config/config.xml b/tests/auto/installer/shared/installer-config/config.xml
new file mode 100644
index 000000000..adc24631b
--- /dev/null
+++ b/tests/auto/installer/shared/installer-config/config.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Installer>
+ <Name>test</Name>
+ <Version>1.0.0</Version>
+</Installer>
diff --git a/tests/auto/installer/shared/packagemanager.h b/tests/auto/installer/shared/packagemanager.h
new file mode 100644
index 000000000..9948be00a
--- /dev/null
+++ b/tests/auto/installer/shared/packagemanager.h
@@ -0,0 +1,82 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#ifndef PACKAGEMANAGER_H
+#define PACKAGEMANAGER_H
+
+#include <packagemanagercore.h>
+#include <binaryformatenginehandler.h>
+#include <binarycontent.h>
+#include <fileutils.h>
+#include <settings.h>
+#include <init.h>
+#include <errors.h>
+
+#include <QTest>
+
+using namespace QInstaller;
+
+void silentTestMessageHandler(QtMsgType, const QMessageLogContext &, const QString &) {}
+void exitOnWarningMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ const QByteArray localMsg = msg.toLocal8Bit();
+ const char *file = context.file ? context.file : "";
+ const char *function = context.function ? context.function : "";
+ if (!(type == QtDebugMsg) && !(type == QtInfoMsg)) {
+ fprintf(stderr, "Caught message: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
+ exit(1);
+ }
+}
+
+struct PackageManager
+{
+ static PackageManagerCore *getPackageManager(const QString &targetDir, const QString &repository = QString())
+ {
+ BinaryFormatEngineHandler::instance()->clear();
+
+ PackageManagerCore *core = new PackageManagerCore(BinaryContent::MagicInstallerMarker, QList<OperationBlob> ());
+ QString appFilePath = QCoreApplication::applicationFilePath();
+ core->disableWriteMaintenanceTool();
+ core->setAutoConfirmCommand();
+ QSet<Repository> repoList;
+ Repository repo = Repository::fromUserInput(repository);
+ repoList.insert(repo);
+ core->settings().setDefaultRepositories(repoList);
+
+ core->setValue(scTargetDir, targetDir);
+ return core;
+ }
+
+ static PackageManagerCore *getPackageManagerWithInit(const QString &targetDir, const QString &repository = QString())
+ {
+ QInstaller::init();
+ qInstallMessageHandler(silentTestMessageHandler);
+ return getPackageManager(targetDir, repository);
+ }
+};
+#endif
diff --git a/tests/auto/installer/shared/verifyinstaller.h b/tests/auto/installer/shared/verifyinstaller.h
new file mode 100644
index 000000000..e19d3fa0a
--- /dev/null
+++ b/tests/auto/installer/shared/verifyinstaller.h
@@ -0,0 +1,139 @@
+/**************************************************************************
+**
+** Copyright (C) 2023 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+
+#ifndef VERIFYINSTALLER_H
+#define VERIFYINSTALLER_H
+
+#include <packagemanagercore.h>
+
+#include <QString>
+#include <QStringList>
+#include <QCryptographicHash>
+#include <QFile>
+#include <QDir>
+#include <QtTest/QTest>
+
+#include <iostream>
+#include <sstream>
+
+struct VerifyInstaller
+{
+ static void verifyInstallerResources(const QString &installDir, const QString &componentName, const QString &fileName)
+ {
+ QDir dir(installDir + QDir::separator() + "installerResources" + QDir::separator() + componentName);
+ QVERIFY2(dir.exists(), qPrintable(QLatin1String("Directory: \"%1\" does not exist").arg(dir.absolutePath())));
+ QFileInfo fileInfo;
+ fileInfo.setFile(dir, fileName);
+ QVERIFY2(fileInfo.exists(), qPrintable(QLatin1String("File: \"%1\" does not exist for \"%2\".")
+ .arg(fileName).arg(componentName)));
+ }
+
+ static void verifyInstallerResourcesDeletion(const QString &installDir, const QString &componentName)
+ {
+ QDir dir(installDir + QDir::separator() + "installerResources" + QDir::separator() + componentName);
+ QVERIFY2(!dir.exists(), qPrintable(QLatin1String("Directory: \"%1\" is not deleted.").arg(dir.absolutePath())));
+ }
+
+ static void verifyInstallerResourceFileDeletion(const QString &installDir, const QString &componentName, const QString &fileName)
+ {
+ QDir dir(installDir + QDir::separator() + "installerResources" + QDir::separator() + componentName);
+ QFileInfo fileInfo;
+ fileInfo.setFile(dir, fileName);
+ QVERIFY2(!fileInfo.exists(), qPrintable(QLatin1String("File: \"%1\" still exists for \"%2\".")
+ .arg(fileName).arg(componentName)));
+ }
+
+ static void verifyFileExistence(const QString &installDir, const QStringList &fileList)
+ {
+ for (int i = 0; i < fileList.count(); i++) {
+ bool fileExists = QFileInfo::exists(installDir + QDir::separator() + fileList.at(i));
+ QVERIFY2(fileExists, QString("File \"%1\" does not exist.").arg(fileList.at(i)).toLatin1());
+ }
+
+ QDir dir(installDir);
+ QCOMPARE(dir.entryList(QStringList() << "*.*", QDir::Files).count(), fileList.count());
+ }
+
+ static QString fileContent(const QString &fileName)
+ {
+ QFile file(fileName);
+ QTextStream stream(&file);
+ file.open(QIODevice::ReadOnly);
+ QString str = stream.readAll();
+ file.close();
+ return str;
+ }
+
+ static void verifyFileContent(const QString &fileName, const QString &content)
+ {
+ QVERIFY(fileContent(fileName).contains(content));
+ }
+
+ static void verifyFileHasNoContent(const QString &fileName, const QString &content)
+ {
+ QVERIFY(!fileContent(fileName).contains(content));
+ }
+
+ static void addToFileMap(const QDir &baseDir, const QFileInfo &fileInfo, QMap<QString, QByteArray> &map)
+ {
+ QDir directory(fileInfo.absoluteFilePath());
+ directory.setFilter(QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::AllDirs | QDir::Files);
+ QFileInfoList fileInfoList = directory.entryInfoList();
+
+ foreach (const QFileInfo &info, fileInfoList) {
+ if (info.isDir()) {
+ map.insert(baseDir.relativeFilePath(info.filePath()), QByteArray());
+ addToFileMap(baseDir, info, map);
+ } else {
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ QFile file(info.absoluteFilePath());
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QVERIFY(hash.addData(&file));
+ map.insert(baseDir.relativeFilePath(info.filePath()), hash.result().toHex());
+ file.close();
+ }
+ }
+ }
+
+ template <typename Func, typename... Args>
+ static void verifyListPackagesMessage(QInstaller::PackageManagerCore *core, const QString &message,
+ Func func, Args... args)
+ {
+ std::ostringstream stream;
+ std::streambuf *buf = std::cout.rdbuf();
+ std::cout.rdbuf(stream.rdbuf());
+
+ (core->*func)(std::forward<Args>(args)...);
+
+ std::cout.rdbuf(buf);
+ QVERIFY(stream && stream.tellp() == message.size());
+ for (const QString &line : message.split(QLatin1String("\n")))
+ QVERIFY(stream.str().find(line.toStdString()) != std::string::npos);
+ }
+};
+#endif
diff --git a/tests/auto/installer/simplemovefileoperation/data/repository/A/1.0.2-1meta.7z b/tests/auto/installer/simplemovefileoperation/data/repository/A/1.0.2-1meta.7z
new file mode 100644
index 000000000..8749fce7f
--- /dev/null
+++ b/tests/auto/installer/simplemovefileoperation/data/repository/A/1.0.2-1meta.7z
Binary files differ
diff --git a/tests/auto/installer/simplemovefileoperation/data/repository/Updates.xml b/tests/auto/installer/simplemovefileoperation/data/repository/Updates.xml
new file mode 100644
index 000000000..6df6a436b
--- /dev/null
+++ b/tests/auto/installer/simplemovefileoperation/data/repository/Updates.xml
@@ -0,0 +1,15 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>A</Name>
+ <DisplayName>A</DisplayName>
+ <Description>Example component A</Description>
+ <Version>1.0.2-1</Version>
+ <ReleaseDate>2015-01-01</ReleaseDate>
+ <Default>true</Default>
+ <Script>script.qs</Script>
+ <SHA1>8f2df84c9eada2570c02a7df573288e5cb6644e2</SHA1>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/simplemovefileoperation/settings.qrc b/tests/auto/installer/simplemovefileoperation/settings.qrc
new file mode 100644
index 000000000..d030220ab
--- /dev/null
+++ b/tests/auto/installer/simplemovefileoperation/settings.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/A/1.0.2-1meta.7z</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/simplemovefileoperation/simplemovefileoperation.pro b/tests/auto/installer/simplemovefileoperation/simplemovefileoperation.pro
new file mode 100644
index 000000000..1cb84824f
--- /dev/null
+++ b/tests/auto/installer/simplemovefileoperation/simplemovefileoperation.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES = tst_simplemovefileoperation.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/simplemovefileoperation/tst_simplemovefileoperation.cpp b/tests/auto/installer/simplemovefileoperation/tst_simplemovefileoperation.cpp
new file mode 100644
index 000000000..9caf7aacf
--- /dev/null
+++ b/tests/auto/installer/simplemovefileoperation/tst_simplemovefileoperation.cpp
@@ -0,0 +1,178 @@
+/**************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+
+#include <simplemovefileoperation.h>
+
+#include <packagemanagercore.h>
+
+#include <utils.h>
+
+#include <QObject>
+#include <QFile>
+#include <QTest>
+
+using namespace KDUpdater;
+using namespace QInstaller;
+
+class tst_simplemovefileoperation : public QObject
+{
+ Q_OBJECT
+
+private:
+ void createDummyFile(const QString &source, const QString &destination)
+ {
+ // Create dummy original file for move destination
+ QFile destFile(destination);
+ QVERIFY(destFile.open(QIODevice::WriteOnly));
+ destFile.close();
+
+ QByteArray testString("Generated by QTest\n");
+ QFile testFile(source);
+ QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text));
+ QTextStream out(&testFile);
+ out << testString;
+ testFile.close();
+ QVERIFY(QFileInfo(source).exists());
+ }
+
+private slots:
+ void testMissingArguments()
+ {
+ SimpleMoveFileOperation op(nullptr);
+
+ op.backup();
+ QVERIFY(op.testOperation());
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::InvalidArguments);
+ QCOMPARE(op.errorString(), QString("Invalid arguments in SimpleMoveFile: "
+ "0 arguments given, exactly 2 arguments expected."));
+
+ op.setArguments(QStringList() << "" << "");
+ QVERIFY(!op.performOperation());
+
+ QCOMPARE(UpdateOperation::Error(op.error()), UpdateOperation::UserDefinedError);
+ QCOMPARE(op.errorString(), QString("None of the arguments can be empty: "
+ "source \"\", target \"\"."));
+ }
+
+ void initTestCase_data()
+ {
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QString>("destination");
+ QTest::newRow("relative") << "test1" << "test2";
+ QTest::newRow("absolute")
+ << qApp->applicationDirPath() + QDir::toNativeSeparators("/test")
+ << generateTemporaryFileName();
+ }
+
+ void testMoveFileWithOverwrite()
+ {
+ QFETCH_GLOBAL(QString, source);
+ QFETCH_GLOBAL(QString, destination);
+
+ createDummyFile(source, destination);
+ QByteArray testFileHash = QInstaller::calculateHash(source, QCryptographicHash::Sha1);
+
+ SimpleMoveFileOperation op(nullptr);
+ op.setArguments(QStringList() << source << destination);
+
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+
+ QVERIFY(!QFileInfo(source).exists());
+ QByteArray destinationFileHash = QInstaller::calculateHash(destination, QCryptographicHash::Sha1);
+ QVERIFY(testFileHash == destinationFileHash);
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+
+ QVERIFY(!QFileInfo(destination).exists());
+ QByteArray sourceFileHash = QInstaller::calculateHash(source, QCryptographicHash::Sha1);
+ QVERIFY(testFileHash == sourceFileHash);
+
+ QVERIFY(QFile(source).remove());
+ }
+
+ void testMoveFileNoUndo()
+ {
+ QFETCH_GLOBAL(QString, source);
+ QFETCH_GLOBAL(QString, destination);
+
+ createDummyFile(source, destination);
+
+ QByteArray testFileHash = QInstaller::calculateHash(source, QCryptographicHash::Sha1);
+
+ SimpleMoveFileOperation op(nullptr);
+ op.setArguments(QStringList() << source << destination << "UNDOOPERATION" << "");
+
+ QVERIFY2(op.performOperation(), op.errorString().toLatin1());
+ QVERIFY(!QFileInfo(source).exists());
+ QByteArray destinationFileHash = QInstaller::calculateHash(destination, QCryptographicHash::Sha1);
+ QVERIFY(testFileHash == destinationFileHash);
+
+ QVERIFY2(op.undoOperation(), op.errorString().toLatin1());
+ QVERIFY(QFileInfo(destination).exists());
+ QVERIFY(testFileHash == destinationFileHash);
+ QVERIFY(QFile(destination).remove());
+ }
+
+ void testPerformingFromCLI()
+ {
+ QString installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(installDir));
+ PackageManagerCore *core = PackageManager::getPackageManagerWithInit
+ (installDir, ":///data/repository");
+
+ QString destinationDir = installDir + QDir::separator() + "destination";
+ QVERIFY(QDir().mkpath(destinationDir));
+
+ // Matches filename in component install script
+ QFile file(installDir + QDir::toNativeSeparators("/test"));
+ QVERIFY(file.open(QIODevice::ReadWrite));
+ file.close();
+
+ core->installDefaultComponentsSilently();
+ QVERIFY(!file.exists());
+
+ QFile movedFile(destinationDir + QDir::separator() + "test");
+ QVERIFY(movedFile.exists());
+
+ core->setPackageManager();
+ core->commitSessionOperations();
+ core->uninstallComponentsSilently(QStringList() << "A");
+ QVERIFY(!movedFile.exists() && file.exists());
+
+ QDir dir(installDir);
+ QVERIFY(dir.removeRecursively());
+ core->deleteLater();
+ }
+};
+
+QTEST_MAIN(tst_simplemovefileoperation)
+
+#include "tst_simplemovefileoperation.moc"
diff --git a/tests/auto/installer/solver/tst_solver.cpp b/tests/auto/installer/solver/tst_solver.cpp
index d1c3aaa14..4548af3f1 100644
--- a/tests/auto/installer/solver/tst_solver.cpp
+++ b/tests/auto/installer/solver/tst_solver.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2023 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -39,13 +39,16 @@
using namespace QInstaller;
typedef QMap<Component *, QStringList> ComponentToStringList;
+typedef QList<QPair<Component *, CalculatorBase::Resolution>> UninstallReasonList;
+
+Q_DECLARE_METATYPE(UninstallReasonList)
class Data {
public:
Data() {}
explicit Data(const QString &data)
: m_data(data) {}
- inline uint qHash(const Data &test);
+ inline hashValue qHash(const Data &test);
QString data() const { return m_data; }
bool operator==(const Data &rhs) const { return m_data == rhs.m_data; }
const Data &operator=(const Data &rhs) { if (this != &rhs) { m_data = rhs.m_data; } return *this; }
@@ -53,7 +56,7 @@ public:
private:
QString m_data;
};
-inline uint qHash(const Data &data)
+inline hashValue qHash(const Data &data)
{
return qHash(data.data());
}
@@ -146,7 +149,8 @@ private slots:
QTest::addColumn<PackageManagerCore *>("core");
QTest::addColumn<QList<Component *> >("selectedComponents");
QTest::addColumn<QList<Component *> >("expectedResult");
- QTest::addColumn<QList<int> >("installReason");
+ QTest::addColumn<QList<CalculatorBase::Resolution> >("installReason");
+ QTest::addColumn<AutoDependencyHash >("autodependencyHash");
PackageManagerCore *core = new PackageManagerCore();
core->setPackageManager();
@@ -166,14 +170,18 @@ private slots:
core->appendRootComponent(componentB_NewVersion);
core->appendRootComponent(componentB_Auto);
+ QHash<QString, QStringList> autodependencyHash;
+ autodependencyHash.insert(QLatin1String("B_version"), QStringList() << QLatin1String("B_auto"));
+
QTest::newRow("Installer resolved") << core
<< (QList<Component *>() << componentB)
<< (QList<Component *>() << componentB_NewVersion << componentAB << componentB << componentB_Auto)
- << (QList<int>()
- << InstallerCalculator::Dependent
- << InstallerCalculator::Dependent
- << InstallerCalculator::Resolved
- << InstallerCalculator::Automatic);
+ << (QList<CalculatorBase::Resolution>()
+ << CalculatorBase::Resolution::Dependent
+ << CalculatorBase::Resolution::Dependent
+ << CalculatorBase::Resolution::Resolved
+ << CalculatorBase::Resolution::Automatic)
+ << autodependencyHash;
}
void resolveInstaller()
@@ -181,16 +189,17 @@ private slots:
QFETCH(PackageManagerCore *, core);
QFETCH(QList<Component *> , selectedComponents);
QFETCH(QList<Component *> , expectedResult);
- QFETCH(QList<int>, installReason);
+ QFETCH(QList<CalculatorBase::Resolution>, installReason);
+ QFETCH(AutoDependencyHash, autodependencyHash);
- InstallerCalculator calc(core->components(PackageManagerCore::ComponentType::AllNoReplacements));
- calc.appendComponentsToInstall(selectedComponents);
- QList<Component *> result = calc.orderedComponentsToInstall();
+ InstallerCalculator calc(core, autodependencyHash);
+ calc.solve(selectedComponents);
+ QList<Component *> result = calc.resolvedComponents();
QCOMPARE(result.count(), expectedResult.count());
for (int i = 0; i < result.count(); i++) {
QCOMPARE(result.at(i), expectedResult.at(i));
- QCOMPARE((int)calc.installReasonType(result.at(i)), installReason.at(i));
+ QCOMPARE(calc.resolutionType(result.at(i)), installReason.at(i));
}
delete core;
}
@@ -218,7 +227,6 @@ private slots:
<< (QList<Component *>() << componentA)
<< (QList<Component *>());
}
-
}
void unresolvedDependencyVersion()
@@ -227,11 +235,11 @@ private slots:
QFETCH(QList<Component *> , selectedComponents);
QFETCH(QList<Component *> , expectedResult);
- InstallerCalculator calc(core->components(PackageManagerCore::ComponentType::AllNoReplacements));
+ InstallerCalculator calc(core, QHash<QString, QStringList>());
QTest::ignoreMessage(QtWarningMsg, "Cannot find missing dependency \"B->=2.0.0\" for \"A\".");
- calc.appendComponentsToInstall(selectedComponents);
+ calc.solve(selectedComponents);
- QList<Component *> result = calc.orderedComponentsToInstall();
+ QList<Component *> result = calc.resolvedComponents();
QCOMPARE(result.count(), expectedResult.count());
delete core;
}
@@ -240,9 +248,11 @@ private slots:
{
QTest::addColumn<PackageManagerCore *>("core");
QTest::addColumn<QList<Component *> >("selectedToUninstall");
- QTest::addColumn<QList<Component *> >("installedComponents");
- QTest::addColumn<QSet<Component *> >("expectedResult");
+ QTest::addColumn<QList<Component *> >("expectedResult");
+ QTest::addColumn<UninstallReasonList >("uninstallReasons");
+ QTest::addColumn<LocalDependencyHash >("dependencyHash");
+ UninstallReasonList uninstallReasonList;
PackageManagerCore *core = new PackageManagerCore();
core->setPackageManager();
NamedComponent *componentA = new NamedComponent(core, QLatin1String("A"));
@@ -259,11 +269,19 @@ private slots:
componentB->setInstalled();
componentAB->setInstalled();
+ QHash<QString, QStringList> dependencyComponentHash;
+ dependencyComponentHash.insert(QLatin1String("A.B"), QStringList() << QLatin1String("B"));
+
+ uninstallReasonList.append(qMakePair(componentAB, CalculatorBase::Resolution::Selected));
+ uninstallReasonList.append(qMakePair(componentB, CalculatorBase::Resolution::Dependent));
QTest::newRow("Uninstaller resolved") << core
<< (QList<Component *>() << componentAB)
- << (QList<Component *>() << componentA << componentB)
- << (QSet<Component *>() << componentAB << componentB);
+ << (QList<Component *>() << componentB << componentAB)
+ << uninstallReasonList
+ << dependencyComponentHash;
+ dependencyComponentHash.clear();
+ uninstallReasonList.clear();
core = new PackageManagerCore();
core->setPackageManager();
NamedComponent *compA = new NamedComponent(core, QLatin1String("A"));
@@ -277,29 +295,37 @@ private slots:
compA->setInstalled();
compB->setInstalled();
+ dependencyComponentHash.insert(QLatin1String("A"), QStringList() << QLatin1String("B"));
+
+ uninstallReasonList.append(qMakePair(compA, CalculatorBase::Resolution::Selected));
+ uninstallReasonList.append(qMakePair(compB, CalculatorBase::Resolution::Dependent));
QTest::newRow("Cascade dependencies") << core
<< (QList<Component *>() << compA)
- << (QList<Component *>() << compB)
- << (QSet<Component *>() << compA << compB);
+ << (QList<Component *>() << compB << compA)
+ << (uninstallReasonList)
+ << dependencyComponentHash;
}
void resolveUninstaller()
{
QFETCH(PackageManagerCore *, core);
QFETCH(QList<Component *> , selectedToUninstall);
- QFETCH(QList<Component *> , installedComponents);
- QFETCH(QSet<Component *> , expectedResult);
-
- UninstallerCalculator calc(installedComponents);
- calc.appendComponentsToUninstall(selectedToUninstall);
- QSet<Component *> result = calc.componentsToUninstall();
-
+ QFETCH(QList<Component *> , expectedResult);
+ QFETCH(UninstallReasonList, uninstallReasons);
+ QFETCH(LocalDependencyHash, dependencyHash);
+
+ UninstallerCalculator calc(core, QHash<QString, QStringList>(), dependencyHash, QStringList());
+ calc.solve(selectedToUninstall);
+ QList<Component *> result = calc.resolvedComponents();
+ for (auto pair : uninstallReasons) {
+ CalculatorBase::Resolution type = calc.resolutionType(pair.first);
+ QCOMPARE(pair.second, type);
+ }
QCOMPARE(result.count(), expectedResult.count());
QCOMPARE(result, expectedResult);
delete core;
}
-
void checkComponent_data()
{
QTest::addColumn<QList<Component *> >("componentsToCheck");
@@ -342,7 +368,6 @@ private slots:
QTest::newRow("AutoDepend and dependency")
<< (QList<Component *>() << componentC << componentD << componentE)
<< result;
-
}
void checkComponent()
diff --git a/tests/auto/installer/treename/data/components.xml b/tests/auto/installer/treename/data/components.xml
new file mode 100644
index 000000000..0cb0e9826
--- /dev/null
+++ b/tests/auto/installer/treename/data/components.xml
@@ -0,0 +1,59 @@
+<Packages>
+ <ApplicationName>Test Application</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Package>
+ <Name>ASub2ToRoot</Name>
+ <Title>Root component 1</Title>
+ <Description>A package without treename (remote treename conflicts with local name)</Description>
+ <TreeName></TreeName>
+ <Version>1.0.0-1</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2021-01-01</InstallDate>
+ <Size>0</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>B</Name>
+ <Title>Root component 2</Title>
+ <Description>A package with treename (remote treename conflicts with local treename)</Description>
+ <TreeName>BSub2ToRoot</TreeName>
+ <Version>1.0.0-1</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2021-01-01</InstallDate>
+ <Size>0</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentB.sub1.sub2</Name>
+ <Title>Sub component</Title>
+ <Description>A package with treename (remote has different treename)</Description>
+ <TreeName>componentC.sub2</TreeName>
+ <Version>1.0.0-1</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2021-01-01</InstallDate>
+ <Size>0</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>C</Name>
+ <Title>Root component 3</Title>
+ <Description>A package with treename (remote name conflicts with local treename)</Description>
+ <TreeName>componentA</TreeName>
+ <Version>1.0.0-1</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2021-01-01</InstallDate>
+ <Size>0</Size>
+ <Checkable>true</Checkable>
+ </Package>
+ <Package>
+ <Name>componentD</Name>
+ <Title>Root component 4</Title>
+ <Description>A package with treename (remote does not have treename)</Description>
+ <TreeName>componentDNew</TreeName>
+ <Version>1.0.0-1</Version>
+ <LastUpdateDate></LastUpdateDate>
+ <InstallDate>2021-01-01</InstallDate>
+ <Size>0</Size>
+ <Checkable>true</Checkable>
+ </Package>
+</Packages>
diff --git a/tests/auto/installer/treename/data/invalid_repository/Updates.xml b/tests/auto/installer/treename/data/invalid_repository/Updates.xml
new file mode 100644
index 000000000..b329bb223
--- /dev/null
+++ b/tests/auto/installer/treename/data/invalid_repository/Updates.xml
@@ -0,0 +1,55 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component depends on componentB.sub2.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentA.sub1</Name>
+ <DisplayName>Component A subcomponent 1</DisplayName>
+ <Description>component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>Component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <TreeName>componentA.sub1</TreeName>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC.sub1</Name>
+ <DisplayName>Component C subcomponent1</DisplayName>
+ <Description>Component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D</DisplayName>
+ <Description>Component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <TreeName moveChildren="true">componentC</TreeName>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD.sub1</Name>
+ <DisplayName>Component D subcomponent 1</DisplayName>
+ <Description>Component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/treename/data/repository/Updates.xml b/tests/auto/installer/treename/data/repository/Updates.xml
new file mode 100644
index 000000000..295f076dd
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/Updates.xml
@@ -0,0 +1,135 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component depends on componentB.sub2.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <Dependencies>componentB.sub2</Dependencies>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>570dec768b1f266c66656f015e772f0e6e41b73d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentA.sub1</Name>
+ <DisplayName>Component A subcomponent 1</DisplayName>
+ <Description>component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>da5819910a7f7c95eb61a49543e273fd6e2e9aae</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentA.sub2</Name>
+ <DisplayName>Component A subcomponent 2</DisplayName>
+ <Description>component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <TreeName>ASub2ToRoot</TreeName>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>73ac2c332ce01fadf0f1c7e16a27faaf0f853e18</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B</DisplayName>
+ <Description>Component B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>72eee5304ff866e024b477d7b2432df8f2428483</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB.sub1</Name>
+ <DisplayName>Component B subcomponent 2 1</DisplayName>
+ <Description>Subcomponent for B</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e19f1a26698afe0b72c9048b403253421b8fed4b</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB.sub1.sub1</Name>
+ <DisplayName>Component B sub component for sub1</DisplayName>
+ <Description>Subsubcomponent for B. Moved to root with treename.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <TreeName>BSub1Sub1ToRoot</TreeName>
+ <UpdateFile CompressedSize="291" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>6a348979273336862c7a5e16305779e81fee1081</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB.sub1.sub2</Name>
+ <DisplayName>Component B second sub component for sub1</DisplayName>
+ <Description>Subsubcomponent for B. Moved under componentC with treename.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <TreeName>componentC.sub1</TreeName>
+ <UpdateFile CompressedSize="291" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c1bca8944147ec64343c146f461288990268b4a9</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB.sub2</Name>
+ <DisplayName>Component B subcomponent 2</DisplayName>
+ <Description>Subcomponent for B. Moved to root with treename.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>8000</SortingPriority>
+ <TreeName>BSub2ToRoot</TreeName>
+ <UpdateFile CompressedSize="283" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>bde9feba3a8134e9c1412b674ee21642938fafec</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentC</Name>
+ <DisplayName>Component C</DisplayName>
+ <Description>Component C</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>cc33e730d9127e1636566ea35bbe4f186ba4bcb7</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentD</Name>
+ <DisplayName>Component D</DisplayName>
+ <Description>Component D. Autodepends on moved item componentA.sub2 </Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <AutoDependOn>componentA.sub2</AutoDependOn>
+ <UpdateFile CompressedSize="275" UncompressedSize="101" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3ca69d6bb062c4442fdb20fe0e62bb0f04e8a419</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentE</Name>
+ <DisplayName>Component E</DisplayName>
+ <Description>Component with tree name, is replaced by other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2022-01-01</ReleaseDate>
+ <TreeName>EToNewRoot</TreeName>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF</Name>
+ <DisplayName>Component F</DisplayName>
+ <Description>Component that replaces other component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2022-01-01</ReleaseDate>
+ <Replaces>componentE</Replaces>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z
new file mode 100644
index 000000000..f7e22c055
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z.sha1
new file mode 100644
index 000000000..3378d2da5
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+d46bf0f128c64749fb03050045afc816774185e2 \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0meta.7z
new file mode 100644
index 000000000..81ff563fc
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z
new file mode 100644
index 000000000..d7f4c781c
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z.sha1
new file mode 100644
index 000000000..0eb4045af
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+6561aae70d055e1c4d72b30b12aef7a85cf2139e \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0meta.7z
new file mode 100644
index 000000000..38d7c557d
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA.sub2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z
new file mode 100644
index 000000000..e50fc1e92
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z.sha1
new file mode 100644
index 000000000..082bcbf64
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+d8486606a02b9c492e4c17d1e42cfea835a1da51 \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentA/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentA/1.0.0meta.7z
new file mode 100644
index 000000000..c062c3cee
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentA/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z
new file mode 100644
index 000000000..2c254e3aa
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z.sha1
new file mode 100644
index 000000000..019ab5051
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+3fd04b8e55846f9622ffb8f9ae5f4e6c8b57f90e \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0meta.7z
new file mode 100644
index 000000000..31630e810
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z
new file mode 100644
index 000000000..261ea6ab9
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z.sha1
new file mode 100644
index 000000000..c3753ca62
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+2e89c27c3590e12cd900cb55fa2c91428babfd45 \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0meta.7z
new file mode 100644
index 000000000..c449e57f6
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1.sub2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z
new file mode 100644
index 000000000..d938d0fb2
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z.sha1
new file mode 100644
index 000000000..3db5bca08
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+2407a2adb3d82211921b509e6dd792d67862de0e \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0meta.7z
new file mode 100644
index 000000000..6996a4d01
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z
new file mode 100644
index 000000000..7319cf08f
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z.sha1
new file mode 100644
index 000000000..855e2edab
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+a8b85ffe4f91b4dc68a6402b314402949ef17a7a \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0meta.7z
new file mode 100644
index 000000000..b91e41207
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB.sub2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z
new file mode 100644
index 000000000..b3a0e683c
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z.sha1
new file mode 100644
index 000000000..377526fb6
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+274b3dbe9cceeca1b577eb2a8302d7690ad93eb3 \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentB/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentB/1.0.0meta.7z
new file mode 100644
index 000000000..e9ab3969d
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentB/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z
new file mode 100644
index 000000000..7eca1e977
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z.sha1
new file mode 100644
index 000000000..d3b44feee
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentC/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+d3015ef5340508ad426c43daa2517c7b62581bab \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentC/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentC/1.0.0meta.7z
new file mode 100644
index 000000000..47ea321ec
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentC/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z b/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z
new file mode 100644
index 000000000..2299f9812
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z.sha1 b/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z.sha1
new file mode 100644
index 000000000..51dcdd0ed
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentD/1.0.0content.7z.sha1
@@ -0,0 +1 @@
+5ce5b91fb7ce209d83ba616ac01bf30e2942f70c \ No newline at end of file
diff --git a/tests/auto/installer/treename/data/repository/componentD/1.0.0meta.7z b/tests/auto/installer/treename/data/repository/componentD/1.0.0meta.7z
new file mode 100644
index 000000000..3443e843b
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository/componentD/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/Updates.xml b/tests/auto/installer/treename/data/repository_children/Updates.xml
new file mode 100644
index 000000000..a17f481d6
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/Updates.xml
@@ -0,0 +1,229 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>false</Checksum>
+ <PackageUpdate>
+ <Name>componentA</Name>
+ <DisplayName>Component A</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <TreeName moveChildren="true">componentANew</TreeName>
+ <UpdateFile UncompressedSize="99" CompressedSize="263" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>8148a84c9a52eb989525f4807482f42c49c743a4</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentA.subcomponent1</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>This component does not have leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="267" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c0c5d273b9c413db07fbd1ffee58759f0059d668</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentB</Name>
+ <DisplayName>Component B (automatic dependency to componentA.subcomponent1)</DisplayName>
+ <Description>This component has an automatic dependency, If the dependency is marked for installation, this component is also installed.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>90</SortingPriority>
+ <AutoDependOn>componentA.subcomponent1</AutoDependOn>
+ <UpdateFile UncompressedSize="99" CompressedSize="263" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>c517b08c40ef5c5984f6bf34a626060dcbab6ba5</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentE</Name>
+ <DisplayName>Component E</DisplayName>
+ <Description>This is a component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>60</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="263" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>2833ea6d508925e64f00fb6b699532992b923ab2</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF</Name>
+ <DisplayName>Component F</DisplayName>
+ <Description>This component contains 2 subcomponents.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>40</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="263" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>21ca242b83ce32dfe066348cbb453080b5967e30</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <TreeName moveChildren="true">FSub1ToRoot</TreeName>
+ <UpdateFile UncompressedSize="99" CompressedSize="267" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>e2745196bceaae476cac330f0af0ce6e564d2d3d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="271" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>8af98107adadb1fda37c1c086c53ed289cc77661</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent1.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="271" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>69458b616989a44e52b480dd9133721bc52b1558</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2</Name>
+ <DisplayName>Subcomponent 2</DisplayName>
+ <Description>This component contains 2 leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <TreeName moveChildren="true">componentE.sub1</TreeName>
+ <UpdateFile UncompressedSize="99" CompressedSize="267" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>9d985ee35442e6e621f8ec24dc41be9f6cab9dad</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent1</Name>
+ <DisplayName>Subsubcomponent 1</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="271" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>43223427efd8c2a428ead343a79709cd1bfc5618</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentF.subcomponent2.subsubcomponent2</Name>
+ <DisplayName>Subsubcomponent 2</DisplayName>
+ <Description>This component does not depend on any other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>50</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="271" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>d76690fb2f41aab262d7d8621c46fa464f35a550</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentH</Name>
+ <DisplayName>Component H</DisplayName>
+ <Description>An example component without dependencies.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>30</SortingPriority>
+ <TreeName moveChildren="true">componentI</TreeName>
+ <UpdateFile UncompressedSize="99" CompressedSize="263" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>04426aec311900e8d74ae42cc6fe49282d314841</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentH.subcomponent1</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>This component does not contain leaf components.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>100</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="267" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>065a901fd86d4e7fd86200da47079c97070178c7</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentI.subcomponent2</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>Subcomponent without original parent.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>30</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="267" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>3d2d928ed10455fe884cab96498a3fc826505406</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentJ</Name>
+ <DisplayName>Component J</DisplayName>
+ <Description>An example component without dependencies.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>30</SortingPriority>
+ <TreeName moveChildren="true">componentJNew</TreeName>
+ <UpdateFile UncompressedSize="99" CompressedSize="263" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>1a46e58cd1824b2c0a4a93d6b27050eb0f6feb29</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentJ.subcomponent1</Name>
+ <DisplayName>Subcomponent 1</DisplayName>
+ <Description>Subcomponent with parent.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>30</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="267" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>dd1cfaa8f6cd14f81635e8917f348006ca7ffdce</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentK</Name>
+ <DisplayName>Component K (depends on componentJ.subcomponent1)</DisplayName>
+ <Description>This component depends on Component J subcomponent.</Description>
+ <Dependencies>componentJ.subcomponent1</Dependencies>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2014-08-25</ReleaseDate>
+ <SortingPriority>80</SortingPriority>
+ <UpdateFile UncompressedSize="99" CompressedSize="263" OS="Any"/>
+ <DownloadableArchives>content.7z</DownloadableArchives>
+ <SHA1>98253c1ab872c9baa64d2fe3525f86a65e73d1f2</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentL</Name>
+ <DisplayName>Component L</DisplayName>
+ <Description>Component with tree name, is replaced by other component.</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2022-01-01</ReleaseDate>
+ <TreeName moveChildren="true">LToNewRoot</TreeName>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentL.sub1</Name>
+ <DisplayName>Component L subcomponent 1</DisplayName>
+ <Description>Child of component L</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2022-01-01</ReleaseDate>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentL.sub2</Name>
+ <DisplayName>Component L subcomponent 2</DisplayName>
+ <Description>Child of component L</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2022-01-01</ReleaseDate>
+ </PackageUpdate>
+ <PackageUpdate>
+ <Name>componentM</Name>
+ <DisplayName>Component M</DisplayName>
+ <Description>Component that replaces other component</Description>
+ <Version>1.0.0</Version>
+ <ReleaseDate>2022-01-01</ReleaseDate>
+ <Replaces>componentL</Replaces>
+ </PackageUpdate>
+</Updates>
diff --git a/tests/auto/installer/treename/data/repository_children/componentA.subcomponent1/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentA.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..095fd7e30
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentA.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentA.subcomponent1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentA.subcomponent1/1.0.0meta.7z
new file mode 100644
index 000000000..5dcce5d73
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentA.subcomponent1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentA/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentA/1.0.0content.7z
new file mode 100644
index 000000000..21d62e629
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentA/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentA/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentA/1.0.0meta.7z
new file mode 100644
index 000000000..094ae8806
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentA/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentB/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentB/1.0.0content.7z
new file mode 100644
index 000000000..2cb5dfee9
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentB/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentB/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentB/1.0.0meta.7z
new file mode 100644
index 000000000..d3ed0961e
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentB/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentE/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentE/1.0.0content.7z
new file mode 100644
index 000000000..cfdef213e
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentE/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentE/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentE/1.0.0meta.7z
new file mode 100644
index 000000000..466926547
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentE/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..3e9297acc
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0meta.7z
new file mode 100644
index 000000000..7adec9a82
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..b715e5587
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0meta.7z
new file mode 100644
index 000000000..69406b1b2
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..f2d2141d7
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1/1.0.0meta.7z
new file mode 100644
index 000000000..1f5c58d2d
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..5307b3de4
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0meta.7z
new file mode 100644
index 000000000..1b44385ab
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..7e83e996e
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0meta.7z
new file mode 100644
index 000000000..c89ac2b7b
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..9c97e4a99
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2/1.0.0meta.7z
new file mode 100644
index 000000000..258b3905f
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF.subcomponent2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentF/1.0.0content.7z
new file mode 100644
index 000000000..12c4c1248
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentF/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentF/1.0.0meta.7z
new file mode 100644
index 000000000..88ec39233
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentF/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentH.subcomponent1/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentH.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..4b2747235
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentH.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentH.subcomponent1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentH.subcomponent1/1.0.0meta.7z
new file mode 100644
index 000000000..ab120d4c3
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentH.subcomponent1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentH/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentH/1.0.0content.7z
new file mode 100644
index 000000000..767f789ff
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentH/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentH/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentH/1.0.0meta.7z
new file mode 100644
index 000000000..e5c9b47c9
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentH/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentI.subcomponent1/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentI.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..2000479c9
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentI.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentI.subcomponent1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentI.subcomponent1/1.0.0meta.7z
new file mode 100644
index 000000000..8ecfeaca8
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentI.subcomponent1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentI.subcomponent2/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentI.subcomponent2/1.0.0content.7z
new file mode 100644
index 000000000..09a8e921a
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentI.subcomponent2/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentI.subcomponent2/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentI.subcomponent2/1.0.0meta.7z
new file mode 100644
index 000000000..acaccd042
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentI.subcomponent2/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentJ.subcomponent1/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentJ.subcomponent1/1.0.0content.7z
new file mode 100644
index 000000000..25247bad4
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentJ.subcomponent1/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentJ.subcomponent1/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentJ.subcomponent1/1.0.0meta.7z
new file mode 100644
index 000000000..c45a63b41
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentJ.subcomponent1/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentJ/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentJ/1.0.0content.7z
new file mode 100644
index 000000000..aa3354b8c
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentJ/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentJ/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentJ/1.0.0meta.7z
new file mode 100644
index 000000000..14b41bdfe
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentJ/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentK/1.0.0content.7z b/tests/auto/installer/treename/data/repository_children/componentK/1.0.0content.7z
new file mode 100644
index 000000000..e28bb9ea7
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentK/1.0.0content.7z
Binary files differ
diff --git a/tests/auto/installer/treename/data/repository_children/componentK/1.0.0meta.7z b/tests/auto/installer/treename/data/repository_children/componentK/1.0.0meta.7z
new file mode 100644
index 000000000..9112f88c3
--- /dev/null
+++ b/tests/auto/installer/treename/data/repository_children/componentK/1.0.0meta.7z
Binary files differ
diff --git a/tests/auto/installer/treename/settings.qrc b/tests/auto/installer/treename/settings.qrc
new file mode 100644
index 000000000..9b31cbade
--- /dev/null
+++ b/tests/auto/installer/treename/settings.qrc
@@ -0,0 +1,65 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data/components.xml</file>
+
+ <file>data/repository/Updates.xml</file>
+ <file>data/repository/componentA/1.0.0meta.7z</file>
+ <file>data/repository/componentA/1.0.0content.7z</file>
+ <file>data/repository/componentA.sub1/1.0.0meta.7z</file>
+ <file>data/repository/componentA.sub1/1.0.0content.7z</file>
+ <file>data/repository/componentA.sub2/1.0.0meta.7z</file>
+ <file>data/repository/componentA.sub2/1.0.0content.7z</file>
+ <file>data/repository/componentB/1.0.0meta.7z</file>
+ <file>data/repository/componentB/1.0.0content.7z</file>
+ <file>data/repository/componentB.sub1/1.0.0meta.7z</file>
+ <file>data/repository/componentB.sub1/1.0.0content.7z</file>
+ <file>data/repository/componentB.sub1.sub1/1.0.0meta.7z</file>
+ <file>data/repository/componentB.sub1.sub1/1.0.0content.7z</file>
+ <file>data/repository/componentB.sub1.sub2/1.0.0meta.7z</file>
+ <file>data/repository/componentB.sub1.sub2/1.0.0content.7z</file>
+ <file>data/repository/componentB.sub2/1.0.0meta.7z</file>
+ <file>data/repository/componentB.sub2/1.0.0content.7z</file>
+ <file>data/repository/componentC/1.0.0meta.7z</file>
+ <file>data/repository/componentC/1.0.0content.7z</file>
+ <file>data/repository/componentD/1.0.0meta.7z</file>
+ <file>data/repository/componentD/1.0.0content.7z</file>
+
+ <file>data/invalid_repository/Updates.xml</file>
+
+ <file>data/repository_children/componentA/1.0.0content.7z</file>
+ <file>data/repository_children/componentA/1.0.0meta.7z</file>
+ <file>data/repository_children/componentA.subcomponent1/1.0.0content.7z</file>
+ <file>data/repository_children/componentA.subcomponent1/1.0.0meta.7z</file>
+ <file>data/repository_children/componentB/1.0.0content.7z</file>
+ <file>data/repository_children/componentB/1.0.0meta.7z</file>
+ <file>data/repository_children/componentE/1.0.0content.7z</file>
+ <file>data/repository_children/componentE/1.0.0meta.7z</file>
+ <file>data/repository_children/componentF/1.0.0content.7z</file>
+ <file>data/repository_children/componentF/1.0.0meta.7z</file>
+ <file>data/repository_children/componentF.subcomponent1/1.0.0content.7z</file>
+ <file>data/repository_children/componentF.subcomponent1/1.0.0meta.7z</file>
+ <file>data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/repository_children/componentF.subcomponent1.subsubcomponent1/1.0.0meta.7z</file>
+ <file>data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/repository_children/componentF.subcomponent1.subsubcomponent2/1.0.0meta.7z</file>
+ <file>data/repository_children/componentF.subcomponent2/1.0.0content.7z</file>
+ <file>data/repository_children/componentF.subcomponent2/1.0.0meta.7z</file>
+ <file>data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0content.7z</file>
+ <file>data/repository_children/componentF.subcomponent2.subsubcomponent1/1.0.0meta.7z</file>
+ <file>data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0content.7z</file>
+ <file>data/repository_children/componentF.subcomponent2.subsubcomponent2/1.0.0meta.7z</file>
+ <file>data/repository_children/componentH/1.0.0content.7z</file>
+ <file>data/repository_children/componentH/1.0.0meta.7z</file>
+ <file>data/repository_children/componentH.subcomponent1/1.0.0content.7z</file>
+ <file>data/repository_children/componentH.subcomponent1/1.0.0meta.7z</file>
+ <file>data/repository_children/componentI.subcomponent2/1.0.0content.7z</file>
+ <file>data/repository_children/componentI.subcomponent2/1.0.0meta.7z</file>
+ <file>data/repository_children/componentJ/1.0.0content.7z</file>
+ <file>data/repository_children/componentJ/1.0.0meta.7z</file>
+ <file>data/repository_children/componentJ.subcomponent1/1.0.0content.7z</file>
+ <file>data/repository_children/componentJ.subcomponent1/1.0.0meta.7z</file>
+ <file>data/repository_children/componentK/1.0.0content.7z</file>
+ <file>data/repository_children/componentK/1.0.0meta.7z</file>
+ <file>data/repository_children/Updates.xml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/installer/treename/treename.pro b/tests/auto/installer/treename/treename.pro
new file mode 100644
index 000000000..97315faad
--- /dev/null
+++ b/tests/auto/installer/treename/treename.pro
@@ -0,0 +1,10 @@
+include(../../qttest.pri)
+
+QT -= gui
+QT += testlib
+
+SOURCES += tst_treename.cpp
+
+RESOURCES += \
+ settings.qrc \
+ ../shared/config.qrc
diff --git a/tests/auto/installer/treename/tst_treename.cpp b/tests/auto/installer/treename/tst_treename.cpp
new file mode 100644
index 000000000..2c8be6ddd
--- /dev/null
+++ b/tests/auto/installer/treename/tst_treename.cpp
@@ -0,0 +1,457 @@
+/**************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Installer Framework.
+**
+** $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$
+**
+**************************************************************************/
+#include "../shared/packagemanager.h"
+#include "../shared/verifyinstaller.h"
+
+#include <packagemanagercore.h>
+#include <component.h>
+#include <componentmodel.h>
+
+#include <QTest>
+#include <QRegularExpression>
+
+class tst_TreeName : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void moveToRoot();
+ void moveToSubItem();
+ void dependencyToMovedItem();
+ void autodependOnMovedItem();
+
+ void moveToExistingAllowUnstableComponents();
+ void moveToExistingItemNoUnstableComponents();
+ void moveWithChildrenChildConflictsAllowUnstable();
+ void moveWithChildrenChildConflictsNoUnstable();
+
+ void moveToRootWithChildren();
+ void moveToSubItemWithChildren();
+ void moveToAvailableParentItemWithChilren();
+ void dependencyToMovedSubItem();
+ void autoDependOnMovedSubItem();
+
+ void replaceComponentWithTreeName();
+ void replaceComponentWithTreeNameMoveChildren();
+
+ void remotePackageConflictsLocal();
+
+ void init();
+ void cleanup();
+
+private:
+ QString m_installDir;
+
+};
+
+void tst_TreeName::moveToRoot()
+{
+ // componentB.sub1.sub1 moved from sub item to root (BSub1Sub1ToRoot)
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentB.sub1.sub1"));
+ QList<Component*> installedComponents = core->orderedComponentsToInstall();
+
+ QCOMPARE(installedComponents.count(), 1);
+ QCOMPARE(installedComponents.at(0)->name(), "componentB.sub1.sub1");
+ QCOMPARE(installedComponents.at(0)->treeName(), "BSub1Sub1ToRoot");
+ QVERIFY(core->componentByName("componentB.sub1.sub1") != 0);
+ QVERIFY(core->componentByName("BSub1Sub1ToRoot") == 0);
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentB.sub1.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "componentBSub1Sub1.txt");
+}
+
+void tst_TreeName::moveToSubItem()
+{
+ // componentB.sub1.sub2 moved under componentC (componentC.sub1)
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository"));
+
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentC"));
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentB.sub1.sub2", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentC", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "componentBSub1Sub2.txt" << "componentC.txt");
+}
+
+void tst_TreeName::dependencyToMovedItem()
+{
+ // componentA depends on componentB.sub2 which is moved to root
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentA"));
+
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA.sub1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentB.sub2", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "componentA.txt" << "componentASub1.txt" << "componentBSub2.txt");
+}
+
+void tst_TreeName::autodependOnMovedItem()
+{
+ // componentD autodepends on componentA.sub2 which is moved to root
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentA.sub2"));
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA.sub2", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentD", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "componentASub2.txt" << "componentD.txt");
+}
+
+void tst_TreeName::moveToExistingAllowUnstableComponents()
+{
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/invalid_repository"));
+ core->settings().setAllowUnstableComponents(true);
+
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentA"));
+ QVERIFY(core->componentByName("componentB")->isUnstable());
+}
+
+void tst_TreeName::moveToExistingItemNoUnstableComponents()
+{
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/invalid_repository"));
+ core->settings().setAllowUnstableComponents(false);
+
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentA"));
+ QVERIFY(!core->componentByName("componentB"));
+}
+
+void tst_TreeName::replaceComponentWithTreeName()
+{
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository"));
+
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentF"));
+ QVERIFY(core->componentByName("componentF")->value(scTreeName).isEmpty());
+ QVERIFY(!core->componentByName("componentE"));
+}
+
+void tst_TreeName::replaceComponentWithTreeNameMoveChildren()
+{
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository_children"));
+
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentM"));
+ QVERIFY(core->componentByName("componentM")->value(scTreeName).isEmpty());
+ QVERIFY(!core->componentByName("componentL"));
+
+ Component *component1 = core->componentByName("componentL.sub1");
+ QCOMPARE(component1->treeName(), component1->name());
+
+ Component *component2 = core->componentByName("componentL.sub2");
+ QCOMPARE(component2->treeName(), component2->name());
+}
+
+void tst_TreeName::moveWithChildrenChildConflictsAllowUnstable()
+{
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/invalid_repository"));
+ core->settings().setAllowUnstableComponents(true);
+
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentD"));
+ Component *const component = core->componentByName("componentD.sub1");
+ QVERIFY(component && component->isUnstable() && !component->isInstalled());
+}
+
+void tst_TreeName::moveWithChildrenChildConflictsNoUnstable()
+{
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/invalid_repository"));
+ core->settings().setAllowUnstableComponents(false);
+
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(QStringList() << "componentD"));
+ QVERIFY(!core->componentByName("componentD.sub1"));
+}
+
+void tst_TreeName::moveToRootWithChildren()
+{
+ // componentF.subcomponent1 moved from sub item to root (FSub1ToRoot)
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository_children"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(
+ QStringList() << "componentF.subcomponent1"));
+ const QList<Component*> installedComponents = core->orderedComponentsToInstall();
+
+ QCOMPARE(installedComponents.count(), 3);
+
+ Component const *parent = installedComponents.at(0);
+ QCOMPARE(parent->name(), "componentF.subcomponent1");
+ QCOMPARE(parent->treeName(), "FSub1ToRoot");
+ QVERIFY(parent->value(scAutoTreeName).isEmpty());
+
+ Component const *child1 = installedComponents.at(1);
+ QCOMPARE(child1->name(), "componentF.subcomponent1.subsubcomponent1");
+ QCOMPARE(child1->treeName(), "FSub1ToRoot.subsubcomponent1");
+ QCOMPARE(child1->treeName(), child1->value(scAutoTreeName));
+
+ Component const *child2 = installedComponents.at(2);
+ QCOMPARE(child2->name(), "componentF.subcomponent1.subsubcomponent2");
+ QCOMPARE(child2->treeName(), "FSub1ToRoot.subsubcomponent2");
+ QCOMPARE(child2->treeName(), child2->value(scAutoTreeName));
+
+ QVERIFY(core->componentByName("componentF.subcomponent1"));
+ QVERIFY(!core->componentByName("FSub1ToRoot"));
+ QVERIFY(core->componentByName("componentF.subcomponent1.subsubcomponent1"));
+ QVERIFY(!core->componentByName("FSub1ToRoot.subsubcomponent1"));
+ QVERIFY(core->componentByName("componentF.subcomponent1.subsubcomponent2"));
+ QVERIFY(!core->componentByName("FSub1ToRoot.subsubcomponent2"));
+
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentF.subcomponent1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentF.subcomponent1.subsubcomponent1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentF.subcomponent1.subsubcomponent2", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "installcontentF_1.txt" << "installcontentF_1_1.txt" << "installcontentF_1_2.txt");
+}
+
+void tst_TreeName::moveToSubItemWithChildren()
+{
+ // componentF.subcomponent2 moved under componentE (componentE.sub1)
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository_children"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(
+ QStringList() << "componentF.subcomponent2"));
+ const QList<Component*> installedComponents = core->orderedComponentsToInstall();
+
+ QCOMPARE(installedComponents.count(), 4);
+
+ Component const *parent = installedComponents.at(1);
+ QCOMPARE(parent->name(), "componentF.subcomponent2");
+ QCOMPARE(parent->treeName(), "componentE.sub1");
+ QVERIFY(parent->value(scAutoTreeName).isEmpty());
+
+ Component const *child1 = installedComponents.at(2);
+ QCOMPARE(child1->name(), "componentF.subcomponent2.subsubcomponent1");
+ QCOMPARE(child1->treeName(), "componentE.sub1.subsubcomponent1");
+ QCOMPARE(child1->treeName(), child1->value(scAutoTreeName));
+
+ Component const *child2 = installedComponents.at(3);
+ QCOMPARE(child2->name(), "componentF.subcomponent2.subsubcomponent2");
+ QCOMPARE(child2->treeName(), "componentE.sub1.subsubcomponent2");
+ QCOMPARE(child2->treeName(), child2->value(scAutoTreeName));
+
+ QVERIFY(core->componentByName("componentF.subcomponent2"));
+ QVERIFY(!core->componentByName("componentE.sub1"));
+ QVERIFY(core->componentByName("componentF.subcomponent2.subsubcomponent1"));
+ QVERIFY(!core->componentByName("componentE.sub1.subsubcomponent1"));
+ QVERIFY(core->componentByName("componentF.subcomponent2.subsubcomponent2"));
+ QVERIFY(!core->componentByName("componentE.sub1.subsubcomponent2"));
+
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentE", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentF.subcomponent2", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentF.subcomponent2.subsubcomponent1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentF.subcomponent2.subsubcomponent2", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "installcontentE.txt" << "installcontentF_2.txt" << "installcontentF_2_1.txt"
+ << "installcontentF_2_2.txt");
+}
+
+void tst_TreeName::moveToAvailableParentItemWithChilren()
+{
+ // componentH moved to componentI
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository_children"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(
+ QStringList() << "componentH"));
+ const QList<Component*> installedComponents = core->orderedComponentsToInstall();
+
+ QCOMPARE(installedComponents.count(), 3);
+
+ Component const *parent = installedComponents.at(0);
+ QCOMPARE(parent->name(), "componentH");
+ QCOMPARE(parent->treeName(), "componentI");
+ QVERIFY(parent->value(scAutoTreeName).isEmpty());
+
+ Component const *child1 = installedComponents.at(1);
+ QCOMPARE(child1->name(), "componentH.subcomponent1");
+ QCOMPARE(child1->treeName(), "componentI.subcomponent1");
+ QCOMPARE(child1->treeName(), child1->value(scAutoTreeName));
+
+ Component const *child2 = installedComponents.at(2);
+ QCOMPARE(child2->name(), "componentI.subcomponent2");
+ QCOMPARE(child2->treeName(), child2->name());
+ QVERIFY(child2->value(scAutoTreeName).isEmpty());
+
+ QVERIFY(core->componentByName("componentH"));
+ QVERIFY(!core->componentByName("componentI"));
+ QVERIFY(core->componentByName("componentH.subcomponent1"));
+ QVERIFY(!core->componentByName("componentI.subcomponent1"));
+ QVERIFY(core->componentByName("componentI.subcomponent2"));
+
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentH", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentH.subcomponent1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentI.subcomponent2", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "installcontentH.txt" << "installcontentH_1.txt" << "installcontentI_2.txt");
+}
+
+void tst_TreeName::dependencyToMovedSubItem()
+{
+ // componentK has dependency to componentJ.subcomponent1, which has a parent with treename
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository_children"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(
+ QStringList() << "componentK"));
+ const QList<Component*> installedComponents = core->orderedComponentsToInstall();
+
+ QCOMPARE(installedComponents.count(), 2);
+
+ Component const *component1 = installedComponents.at(0);
+ QCOMPARE(component1->name(), "componentJ.subcomponent1");
+ QCOMPARE(component1->treeName(), "componentJNew.subcomponent1");
+ QCOMPARE(component1->treeName(), component1->value(scAutoTreeName));
+
+ Component const *component2 = installedComponents.at(1);
+ QCOMPARE(component2->name(), "componentK");
+ QCOMPARE(component2->treeName(), component2->name());
+ QVERIFY(component2->value(scAutoTreeName).isEmpty());
+
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentJ.subcomponent1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentK", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "installcontentJ_1.txt" << "installcontentK.txt");
+}
+
+void tst_TreeName::autoDependOnMovedSubItem()
+{
+ // componentB auto-depends on componentA.subcomponent1, which has a parent with treename
+ QScopedPointer<PackageManagerCore> core(PackageManager::getPackageManagerWithInit
+ (m_installDir, ":///data/repository_children"));
+ QCOMPARE(PackageManagerCore::Success, core->installSelectedComponentsSilently(
+ QStringList() << "componentA.subcomponent1"));
+ const QList<Component*> installedComponents = core->orderedComponentsToInstall();
+
+ QCOMPARE(installedComponents.count(), 3);
+
+ Component const *component1 = installedComponents.at(0);
+ QCOMPARE(component1->name(), "componentA");
+ QCOMPARE(component1->treeName(), "componentANew");
+ QVERIFY(component1->value(scAutoTreeName).isEmpty());
+
+ Component const *component2 = installedComponents.at(1);
+ QCOMPARE(component2->name(), "componentA.subcomponent1");
+ QCOMPARE(component2->treeName(), "componentANew.subcomponent1");
+ QCOMPARE(component2->treeName(), component2->value(scAutoTreeName));
+
+ Component const *component3 = installedComponents.at(2);
+ QCOMPARE(component3->name(), "componentB");
+ QCOMPARE(component3->treeName(), component3->name());
+
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentA", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir,
+ "componentA.subcomponent1", "1.0.0content.txt");
+ VerifyInstaller::verifyInstallerResources(m_installDir, "componentB", "1.0.0content.txt");
+ VerifyInstaller::verifyFileExistence(m_installDir, QStringList() << "components.xml"
+ << "installcontentA.txt" << "installcontentA_1.txt" << "installcontentB.txt");
+}
+
+void tst_TreeName::remotePackageConflictsLocal()
+{
+ const QString packageHubFile = qApp->applicationDirPath() + QDir::separator() + "components.xml";
+ QFile::remove(packageHubFile);
+ QVERIFY(QFile::copy(":///data/components.xml", packageHubFile));
+ // For some reason Windows sets the read-only flag when we copy the resource..
+ QVERIFY(setDefaultFilePermissions(packageHubFile, DefaultFilePermissions::NonExecutable));
+
+ QHash<QString, QString> params;
+ params.insert(scTargetDir, qApp->applicationDirPath());
+ PackageManagerCore core(BinaryContent::MagicPackageManagerMarker, QList<OperationBlob>(),
+ QString(), QString(), Protocol::DefaultAuthorizationKey, Protocol::Mode::Production, params);
+
+ core.settings().setAllowUnstableComponents(true);
+ core.settings().setDefaultRepositories(QSet<Repository>()
+ << Repository::fromUserInput(":///data/repository"));
+
+ QVERIFY(core.fetchRemotePackagesTree());
+ {
+ // Remote treename conflicts with local name
+ Component *const local = core.componentByName("ASub2ToRoot");
+ QVERIFY(local && local->isInstalled());
+
+ Component *const remote = core.componentByName("componentA.sub2");
+ QVERIFY(remote && remote->isUnstable());
+ QCOMPARE(remote->treeName(), remote->name());
+ }
+ {
+ // Remote treename conflicts with local treename
+ Component *const local = core.componentByName("B");
+ QVERIFY(local && local->isInstalled() && local->treeName() == "BSub2ToRoot");
+
+ Component *const remote = core.componentByName("componentB.sub2");
+ QVERIFY(remote && remote->isUnstable());
+ QCOMPARE(remote->treeName(), remote->name());
+ }
+ {
+ // Remote name conflicts with local treename
+ Component *const local = core.componentByName("C");
+ QVERIFY(local && local->isInstalled() && local->treeName() == "componentA");
+
+ Component *const remote = core.componentByName("componentA");
+ QVERIFY(!remote);
+ }
+ {
+ // Component has a treename in local but not in remote, add with local treename
+ Component *const component = core.componentByName("componentD");
+ QVERIFY(component && component->isInstalled() && component->treeName() == "componentDNew");
+ }
+ {
+ // Component has different treename in local and remote, add with local treename
+ Component *const component = core.componentByName("componentB.sub1.sub2");
+ QVERIFY(component && component->isInstalled() && component->treeName() == "componentC.sub2");
+ }
+ QVERIFY(QFile::remove(packageHubFile));
+}
+
+void tst_TreeName::init()
+{
+ m_installDir = QInstaller::generateTemporaryFileName();
+ QVERIFY(QDir().mkpath(m_installDir));
+}
+
+void tst_TreeName::cleanup()
+{
+ QDir dir(m_installDir);
+ QVERIFY(dir.removeRecursively());
+}
+
+QTEST_MAIN(tst_TreeName)
+
+#include "tst_treename.moc"
diff --git a/tests/auto/installer/unicodeexecutable/main.c b/tests/auto/installer/unicodeexecutable/main.c
index d82e0cb60..bce0321ab 100644
--- a/tests/auto/installer/unicodeexecutable/main.c
+++ b/tests/auto/installer/unicodeexecutable/main.c
@@ -1,32 +1,26 @@
/**************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $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 http://qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
+** 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$
**
diff --git a/tests/auto/installer/unicodeexecutable/stringdata.h b/tests/auto/installer/unicodeexecutable/stringdata.h
index 901fac31a..f938374fa 100644
--- a/tests/auto/installer/unicodeexecutable/stringdata.h
+++ b/tests/auto/installer/unicodeexecutable/stringdata.h
@@ -1,32 +1,26 @@
/**************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $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 http://qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
+** 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$
**