aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorJake Petroules <jake.petroules@qt.io>2016-04-22 01:20:24 -0700
committerIvan Komissarov <ABBAPOH@gmail.com>2021-02-18 00:10:00 +0000
commit2bc823ec00cec8a1d58981710eb50ba85b4f58d7 (patch)
tree4397fc51e963e00f8ab6dbf7686d5e28cda40c01 /tests
parent05b74ff728e8c6bc975e8c55160e1feb137895a1 (diff)
Implement codesign module
This moves code signing functionality into a dedicated module, and also implements automatic provisioning for Apple platforms, which automatically selects appropriate signing identities and provisioning profiles based on the product being built. This also results in a significant performance improvement since all code signing setup information is retrieved in process instead of forking off the openssl and security command line tools. Task-number: QBS-899 Change-Id: I60d0aeaeb2d1004929505bcb1e0bc77512fe77bc Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/api/tst_api.cpp4
-rw-r--r--tests/auto/blackbox/testdata-apple/codesign/app.cpp1
-rw-r--r--tests/auto/blackbox/testdata-apple/codesign/codesign.qbs38
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp4
-rw-r--r--tests/auto/blackbox/tst_blackboxapple.cpp99
-rw-r--r--tests/auto/blackbox/tst_blackboxapple.h2
-rw-r--r--tests/auto/blackbox/tst_blackboxbase.h9
7 files changed, 153 insertions, 4 deletions
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index 7a585f641..a51eb3e0c 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -2507,7 +2507,9 @@ qbs::SetupProjectParameters TestApi::defaultSetupParameters(const QString &proje
}
qbs::SetupProjectParameters setupParams;
- setupParams.setEnvironment(QProcessEnvironment::systemEnvironment());
+ auto environment = QProcessEnvironment::systemEnvironment();
+ environment.insert("QBS_AUTOTEST_CODE_SIGNING_REQUIRED", "0");
+ setupParams.setEnvironment(environment);
setupParams.setProjectFilePath(projectFilePath);
setupParams.setPropertyCheckingMode(qbs::ErrorHandlingMode::Strict);
setupParams.setOverrideBuildGraphData(true);
diff --git a/tests/auto/blackbox/testdata-apple/codesign/app.cpp b/tests/auto/blackbox/testdata-apple/codesign/app.cpp
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/codesign/app.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs b/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs
new file mode 100644
index 000000000..312e9f001
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs
@@ -0,0 +1,38 @@
+Project {
+ name: "p"
+
+ property bool isBundle: true
+ property bool enableSigning: true
+
+ CppApplication {
+ name: "A"
+ bundle.isBundle: project.isBundle
+ files: "app.cpp"
+ codesign.enableCodeSigning: project.enableSigning
+ codesign.signingType: "ad-hoc"
+ install: true
+ installDir: ""
+ }
+
+ DynamicLibrary {
+ Depends { name: "cpp" }
+ name: "B"
+ bundle.isBundle: project.isBundle
+ files: "app.cpp"
+ codesign.enableCodeSigning: project.enableSigning
+ codesign.signingType: "ad-hoc"
+ install: true
+ installDir: ""
+ }
+
+ LoadableModule {
+ Depends { name: "cpp" }
+ name: "C"
+ bundle.isBundle: project.isBundle
+ files: "app.cpp"
+ codesign.enableCodeSigning: project.enableSigning
+ codesign.signingType: "ad-hoc"
+ install: true
+ installDir: ""
+ }
+}
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 20116ff56..2a3c40124 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -2173,7 +2173,7 @@ void TestBlackbox::trackExternalProductChanges()
const QStringList toolchainTypes = profileToolchain(profile);
if (!toolchainTypes.contains("gcc"))
QSKIP("Need GCC-like compiler to run this test");
- params.environment = QProcessEnvironment::systemEnvironment();
+ params.environment = QbsRunParameters::defaultEnvironment();
params.environment.insert("INCLUDE_PATH_TEST", "1");
params.expectFailure = true;
QVERIFY(runQbs(params) != 0);
@@ -6054,7 +6054,7 @@ void TestBlackbox::qbsSession()
QJsonObject overriddenValues;
overriddenValues.insert("products.theLib.cpp.cxxLanguageVersion", "c++17");
resolveMessage.insert("overridden-properties", overriddenValues);
- resolveMessage.insert("environment", envToJson(QProcessEnvironment::systemEnvironment()));
+ resolveMessage.insert("environment", envToJson(QbsRunParameters::defaultEnvironment()));
resolveMessage.insert("data-mode", "only-if-changed");
resolveMessage.insert("log-time", true);
resolveMessage.insert("module-properties",
diff --git a/tests/auto/blackbox/tst_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp
index adde389ec..8915ac8b2 100644
--- a/tests/auto/blackbox/tst_blackboxapple.cpp
+++ b/tests/auto/blackbox/tst_blackboxapple.cpp
@@ -140,6 +140,39 @@ static QString findFatLibrary(const QString &dir, const QString &libraryName)
return {};
}
+enum class CodeSignResult { Failed = 0, Signed, Unsigned };
+using CodeSignData = QMap<QByteArray, QByteArray>;
+static std::pair<CodeSignResult, CodeSignData> parseCodeSignOutput(const QByteArray &output)
+{
+ CodeSignData data;
+ if (output.contains("code object is not signed at all"))
+ return {CodeSignResult::Unsigned, data};
+ const auto lines = output.split('\n');
+ for (const auto &line: lines) {
+ if (line.isEmpty()
+ || line.startsWith("CodeDirectory")
+ || line.startsWith("Sealed Resources")
+ || line.startsWith("Internal requirements")) {
+ continue;
+ }
+ const int index = line.indexOf('=');
+ if (index == -1)
+ return {CodeSignResult::Failed, {}};
+ data[line.mid(0, index)] = line.mid(index + 1);
+ }
+ return {CodeSignResult::Signed, data};
+}
+
+static std::pair<CodeSignResult, CodeSignData> getCodeSignInfo(const QString &path)
+{
+ QProcess codesign;
+ codesign.start("codesign", { QStringLiteral("-dv"), path });
+ if (!codesign.waitForStarted() || !codesign.waitForFinished())
+ return {CodeSignResult::Failed, {}};
+ const auto output = codesign.readAllStandardError();
+ return parseCodeSignOutput(output);
+}
+
TestBlackboxApple::TestBlackboxApple()
: TestBlackboxBase (SRCDIR "/testdata-apple", "blackbox-apple")
{
@@ -680,6 +713,72 @@ void TestBlackboxApple::bundleStructure_data()
QTest::newRow("G") << "G" << "com.apple.product-type.in-app-purchase-content";
}
+void TestBlackboxApple::codesign()
+{
+ QFETCH(bool, isBundle);
+ QFETCH(bool, enableSigning);
+
+ QDir::setCurrent(testDataDir + "/codesign");
+ QbsRunParameters params(QStringList{"qbs.installPrefix:''"});
+ params.arguments
+ << QStringLiteral("project.isBundle:%1").arg(isBundle ? "true" : "false");
+ params.arguments
+ << QStringLiteral("project.enableSigning:%1").arg(enableSigning ? "true" : "false");
+
+ rmDirR(relativeBuildDir());
+ QCOMPARE(runQbs(params), 0);
+
+ const auto appName = isBundle ? QStringLiteral("A.app") : QStringLiteral("A");
+ const auto appPath = defaultInstallRoot + "/" + appName;
+ QVERIFY(QFileInfo(appPath).exists());
+ auto codeSignInfo = getCodeSignInfo(appPath);
+ QVERIFY(codeSignInfo.first != CodeSignResult::Failed);
+ QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, enableSigning);
+ QCOMPARE(codeSignInfo.second.isEmpty(), !enableSigning);
+ if (!codeSignInfo.second.isEmpty()) {
+ QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable")));
+ QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier")));
+ QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc");
+ }
+
+ const auto libName = isBundle ? QStringLiteral("B.framework") : QStringLiteral("libB.dylib");
+ const auto libPath = defaultInstallRoot + "/" + libName;
+ QVERIFY(QFileInfo(libPath).exists());
+ codeSignInfo = getCodeSignInfo(libPath);
+ QVERIFY(codeSignInfo.first != CodeSignResult::Failed);
+ QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, enableSigning);
+ QCOMPARE(codeSignInfo.second.isEmpty(), !enableSigning);
+ if (!codeSignInfo.second.isEmpty()) {
+ QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable")));
+ QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier")));
+ QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc");
+ }
+
+ const auto pluginPath = defaultInstallRoot + "/" + QStringLiteral("C.bundle");
+ QVERIFY(QFileInfo(pluginPath).exists());
+ QVERIFY(QFileInfo(pluginPath).isDir() == isBundle);
+ codeSignInfo = getCodeSignInfo(pluginPath);
+ QVERIFY(codeSignInfo.first != CodeSignResult::Failed);
+ QCOMPARE(codeSignInfo.first == CodeSignResult::Signed, enableSigning);
+ QCOMPARE(codeSignInfo.second.isEmpty(), !enableSigning);
+ if (!codeSignInfo.second.isEmpty()) {
+ QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Executable")));
+ QVERIFY(codeSignInfo.second.contains(QByteArrayLiteral("Identifier")));
+ QCOMPARE(codeSignInfo.second.value(QByteArrayLiteral("Signature")), "adhoc");
+ }
+}
+
+void TestBlackboxApple::codesign_data()
+{
+ QTest::addColumn<bool>("isBundle");
+ QTest::addColumn<bool>("enableSigning");
+
+ QTest::newRow("bundle, unsigned") << true << false;
+ QTest::newRow("standalone, unsigned") << false << false;
+ QTest::newRow("bundle, signed") << true << true;
+ QTest::newRow("standalone, signed") << false << true;
+}
+
void TestBlackboxApple::deploymentTarget()
{
QFETCH(QString, sdk);
diff --git a/tests/auto/blackbox/tst_blackboxapple.h b/tests/auto/blackbox/tst_blackboxapple.h
index eeaa28d2f..32eee2432 100644
--- a/tests/auto/blackbox/tst_blackboxapple.h
+++ b/tests/auto/blackbox/tst_blackboxapple.h
@@ -55,6 +55,8 @@ private slots:
void assetCatalogsMultiple();
void bundleStructure();
void bundleStructure_data();
+ void codesign();
+ void codesign_data();
void deploymentTarget();
void deploymentTarget_data();
void dmg();
diff --git a/tests/auto/blackbox/tst_blackboxbase.h b/tests/auto/blackbox/tst_blackboxbase.h
index ed9a233de..d020b7cd9 100644
--- a/tests/auto/blackbox/tst_blackboxbase.h
+++ b/tests/auto/blackbox/tst_blackboxbase.h
@@ -60,7 +60,14 @@ public:
expectCrash = false;
profile = profileName();
settingsDir = settings()->baseDirectory();
- environment = QProcessEnvironment::systemEnvironment();
+ environment = defaultEnvironment();
+ }
+
+ static QProcessEnvironment defaultEnvironment()
+ {
+ auto result = QProcessEnvironment::systemEnvironment();
+ result.insert(QStringLiteral("QBS_AUTOTEST_CODE_SIGNING_REQUIRED"), QStringLiteral("0"));
+ return result;
}
QString command;