-
Notifications
You must be signed in to change notification settings - Fork 0
Test coverage for codesigned updates #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| "use strict"; | ||
|
|
||
| import crypto = require("crypto"); | ||
| import fs = require("fs"); | ||
| import mkdirp = require("mkdirp"); | ||
| import path = require("path"); | ||
|
|
||
| import { Platform, ProjectManager, ServerUtil, setupUpdateScenario, TestConfig, TestUtil } from "code-push-plugin-testing-framework"; | ||
|
|
||
| const CODEPUSH_METADATA_FILE_NAME = ".codepushrelease"; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This and the next few functions are existing code, moving from |
||
|
|
||
| function isHashIgnored(relativePath: string): boolean { | ||
| return relativePath.startsWith("__MACOSX/") | ||
| || relativePath === ".DS_Store" | ||
| || relativePath.endsWith("/.DS_Store") | ||
| || relativePath === CODEPUSH_METADATA_FILE_NAME | ||
| || relativePath.endsWith(`/${CODEPUSH_METADATA_FILE_NAME}`); | ||
| } | ||
|
|
||
| /** | ||
| * Computes the same content hash that the native SDKs compute over an installed update folder, so the mock server | ||
| * can hand back a package_hash that will actually match what the client expects. | ||
| */ | ||
| export function computeUpdateContentsHash(folderPath: string): string { | ||
| const manifest: string[] = []; | ||
|
|
||
| const walk = (currentPath: string, relativePrefix: string) => { | ||
| for (const entryName of fs.readdirSync(currentPath)) { | ||
| const entryPath = path.join(currentPath, entryName); | ||
| const relativePath = relativePrefix ? `${relativePrefix}/${entryName}` : entryName; | ||
|
|
||
| if (isHashIgnored(relativePath)) { | ||
| continue; | ||
| } | ||
|
|
||
| if (fs.statSync(entryPath).isDirectory()) { | ||
| walk(entryPath, relativePath); | ||
| } else { | ||
| const fileHash = crypto.createHash("sha256").update(fs.readFileSync(entryPath)).digest("hex"); | ||
| manifest.push(`${relativePath}:${fileHash}`); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| walk(folderPath, ""); | ||
| manifest.sort(); | ||
|
|
||
| return crypto.createHash("sha256").update(JSON.stringify(manifest)).digest("hex"); | ||
| } | ||
|
ofalvai marked this conversation as resolved.
|
||
|
|
||
| const codeSigningPrivateKey = fs.readFileSync(path.join(__dirname, "../test/fixtures/codesigning/test-private-key.pem"), "utf8"); | ||
| export const codeSigningPublicKey = fs.readFileSync(path.join(__dirname, "../test/fixtures/codesigning/test-public-key.pem"), "utf8").trim(); | ||
|
|
||
| function base64UrlEncode(input: Buffer): string { | ||
| return input.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); | ||
| } | ||
|
|
||
| /** | ||
| * Builds the RS256-signed ".codepushrelease" JWT that the native SDKs look for inside an update | ||
| * archive's "CodePush/" folder. | ||
| */ | ||
| function signUpdateContentsHash(contentHash: string): string { | ||
| const header = base64UrlEncode(Buffer.from(JSON.stringify({ alg: "RS256", typ: "JWT" }))); | ||
| const payload = base64UrlEncode(Buffer.from(JSON.stringify({ contentHash }))); | ||
| const signature = base64UrlEncode(crypto.sign("RSA-SHA256", Buffer.from(`${header}.${payload}`), codeSigningPrivateKey)); | ||
| return `${header}.${payload}.${signature}`; | ||
| } | ||
|
|
||
| /** | ||
| * Code-signs the update contents with the test key pair and records the real hash, so the mock | ||
| * server hands back a package_hash that matches what the client's data-integrity check computes. | ||
| */ | ||
| export function signAndRecordUpdateArchive(bundleFolder: string, isDiff: boolean): void { | ||
| // TODO(RA-4875): Diff updates clear it instead, since they are poorly implemented in the entire test harness. | ||
| // It's going to be a bigger refactor, so for now we just skip signing/hashing to avoid using a stale value in diff tests. | ||
| if (isDiff) { | ||
| ServerUtil.setKnownPackageHash(undefined); | ||
| return; | ||
| } | ||
|
|
||
| const contentHash = computeUpdateContentsHash(bundleFolder); | ||
| const signatureFolder = path.join(bundleFolder, "CodePush"); | ||
| mkdirp.sync(signatureFolder); | ||
| fs.writeFileSync(path.join(signatureFolder, CODEPUSH_METADATA_FILE_NAME), signUpdateContentsHash(contentHash)); | ||
| ServerUtil.setKnownPackageHash(contentHash); | ||
| } | ||
|
|
||
| export async function setupTamperedSignatureUpdateScenario(projectManager: ProjectManager, targetPlatform: Platform.IPlatform, scenarioJsPath: string, version: string): Promise<string> { | ||
| const updatePath = await setupUpdateScenario(projectManager, targetPlatform, scenarioJsPath, version); | ||
|
|
||
| const bundleFolder = path.join(TestConfig.updatesDirectory, TestConfig.TestAppName, "CodePush/"); | ||
| const tamperedHash = "0".repeat(64); | ||
| fs.writeFileSync(path.join(bundleFolder, "CodePush", CODEPUSH_METADATA_FILE_NAME), signUpdateContentsHash(tamperedHash)); | ||
|
|
||
| return await TestUtil.archiveFolder(bundleFolder, "", updatePath, false); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| -----BEGIN RSA PRIVATE KEY----- | ||
| MIIEpQIBAAKCAQEApZtuvtGcQmmeUh81n/jAjeDkktkX1QryINqRZrcoofjw+w89 | ||
| FdW3XxQOhsjIJLr5u0xqjHde6Hzpx9sbcUGivmW1O0HBuCsAeiVHyiTq/t+sEiKP | ||
| 0VZa1mbnSM3EEQl09Si3NpLs4sHK+uvttLT3KEZy+Zhx54gaM5iz7ErqavpDADaW | ||
| DWplIXUK/D/pQulbM1oM+04V1XkKw5bBqEHTi6Whq/YUPWs2+7KXyLnvKyO+33YF | ||
| WnHhHGbGkGLYE02sAGonYgaP220vJ4lnwLx0OcEagfdlM8YwfyOUSWn7LB0VCJaz | ||
| ltDiuM1ZhL1rDA8d0rHZvtxKJDLz3uIRuppj7wIDAQABAoIBAAIEOH7+UmbEnnbl | ||
| hmOiRcX0fRQErLOdZIFd5/NWO5ptS5HjB51ics8nkV22yCkaVbwgHBQFyBQQoVAb | ||
| rOPeJrsmxeQo0tEJRQI3vf4KIQplctTtss6bvJNrwVkzmDWU5eWuTzzM4TGJpo0T | ||
| nlta8L9+zBuZ7ZkiIR+LtnUkHGKdEHKFD4melmeZrvMCDNTGrpa2Y2bP9I11a6xZ | ||
| V1XJIxvAQRftorz03vsQXFiIcscEaho65DiAObSqpn1tfFnTbPOl+z4XjKncAVF8 | ||
| 5vmkVHvERnvUuuBmSTEgGrEcCgwmYKxtOGqWw3MpeP9DWroU5T1N/Mx5xTr3GID5 | ||
| 6T3+bMECgYEA6Kyg43UCouS7LD/lB5z0dflK8Wu0hzdYUR58r4e2S/WhzkiyX1rZ | ||
| aJNkrxyC8/39lGrYdfJHc+RNbViC1TMfH7Zao1lNFVP7vF70v2HzishCL95wSXNz | ||
| KZnSY3Yac1ONVP8ZbxX20QBXh9aoTsQxtOs15+XBvOXA5kJwtaaPgTECgYEAtjWW | ||
| UiLznuODzIyOQugysXN9bU0UTqUxr3QDt0yqCjA0URVlf3Ehi7OVUPerVSwgCD5m | ||
| 4RXltW8pqMCLY/qPLkVFH+uZJ/Oo495TEMbyk2/4GXEX4klBMW40YI5srFtP95k+ | ||
| HrW5+gFOoVLcpwxRHcW6JateA7RlZDReruAt7x8CgYEAgcQdqx4MTVsyRNiR3LAd | ||
| 61oRARpnwe4NFJjjQ2Z2NmEVUB5dVS8vB9MEmWFWa8whTFBWz1lDnpAa2rw9o7hy | ||
| SFaEsIvSoO2I/aMb700q7iEIQPhXOa/o76+5lf09fUqBDYGE5t6iHCiLqNgAYIWt | ||
| j1CLbP1IExk0f3dYswblDFECgYEAkib5pHiUoWYtWe2ETvahcuUIPpwNJegrqmiM | ||
| coL0AagYztEy0L6WAdDSfFes/myeZP5o1zMRRi8cY1fOdyuLnbnCcJAyEXHIjr7O | ||
| Mi7idJDjmMS2O7Q2rsePC8QyNy4nPpuU0F1EB9z0jUJB61xd1Fu9rGmAx8fzbCT1 | ||
| rZ/0OFECgYEAwQHaF2oxQMxd/WzuTHtKYuPAJDvONQj+hcEAEVFUGEVnauRoUuta | ||
| rhgnWrD2rte/6JqGPnfJouW+w1Y+2Mnfp4io8/cyysiEX7VWTeZL+nUERczTserl | ||
| cyujq12LNdD+YPQwJTxHguP0rbMsQ2lHlxwys1+74GGq7GqR3dIJlqc= | ||
| -----END RSA PRIVATE KEY----- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| -----BEGIN PUBLIC KEY----- | ||
| MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZtuvtGcQmmeUh81n/jA | ||
| jeDkktkX1QryINqRZrcoofjw+w89FdW3XxQOhsjIJLr5u0xqjHde6Hzpx9sbcUGi | ||
| vmW1O0HBuCsAeiVHyiTq/t+sEiKP0VZa1mbnSM3EEQl09Si3NpLs4sHK+uvttLT3 | ||
| KEZy+Zhx54gaM5iz7ErqavpDADaWDWplIXUK/D/pQulbM1oM+04V1XkKw5bBqEHT | ||
| i6Whq/YUPWs2+7KXyLnvKyO+33YFWnHhHGbGkGLYE02sAGonYgaP220vJ4lnwLx0 | ||
| OcEagfdlM8YwfyOUSWn7LB0VCJazltDiuM1ZhL1rDA8d0rHZvtxKJDLz3uIRuppj | ||
| 7wIDAQAB | ||
| -----END PUBLIC KEY----- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,19 +2,24 @@ | |
|
|
||
| import assert = require("assert"); | ||
| import childProcess = require("child_process"); | ||
| import crypto = require("crypto"); | ||
| import fs = require("fs"); | ||
| import mkdirp = require("mkdirp"); | ||
| import os = require("os"); | ||
| import path = require("path"); | ||
| import slash = require("slash"); | ||
| import { promisify } from "util"; | ||
|
|
||
| import { Platform, PluginTestingFramework, ProjectManager, setupTestRunScenario, setupUpdateScenario, ServerUtil, TestBuilder, TestConfig, TestUtil } from "code-push-plugin-testing-framework"; | ||
|
|
||
| import Q = require("q"); | ||
|
|
||
| import del = require("del"); | ||
|
|
||
| import { codeSigningPublicKey, signAndRecordUpdateArchive, setupTamperedSignatureUpdateScenario } from "./codesign"; | ||
|
|
||
| // Used in test/template/app.json to avoid duplicating the PEM fixture in two places (ios and android plugin config). | ||
| const CODE_SIGNING_PUBLIC_KEY_PLACEHOLDER = "{{CODE_SIGNING_PUBLIC_KEY}}"; | ||
|
|
||
| function ensureAndroidCleartextTraffic(androidManifestPath: string): void { | ||
| const androidManifestContents = fs.readFileSync(androidManifestPath, "utf8"); | ||
|
|
||
|
|
@@ -37,6 +42,10 @@ function ensureAndroidCleartextTraffic(androidManifestPath: string): void { | |
| } | ||
| } | ||
|
|
||
| async function setPlistStringValue(plistPath: string, key: string, value: string): Promise<void> { | ||
| await promisify(childProcess.execFile)("plutil", ["-replace", key, "-string", value, plistPath]); | ||
| } | ||
|
|
||
| /** | ||
| * Returns a " --platform <ios|android>" flag for `expo prebuild` when exactly one platform is | ||
| * under test in this mocha run, so prebuild only regenerates that platform's native project | ||
|
|
@@ -69,47 +78,6 @@ function installExpoBundleTooling(projectPath: string): Q.Promise<void> { | |
| ).then(() => { return null; }); | ||
| } | ||
|
|
||
| const CODEPUSH_METADATA_FILE_NAME = ".codepushrelease"; | ||
|
|
||
| function isHashIgnored(relativePath: string): boolean { | ||
| return relativePath.startsWith("__MACOSX/") | ||
| || relativePath === ".DS_Store" | ||
| || relativePath.endsWith("/.DS_Store") | ||
| || relativePath === CODEPUSH_METADATA_FILE_NAME | ||
| || relativePath.endsWith(`/${CODEPUSH_METADATA_FILE_NAME}`); | ||
| } | ||
|
|
||
| /** | ||
| * Computes the same content hash that the native SDKs compute over an installed update folder, so the mock server | ||
| * can hand back a package_hash that will actually match what the client expects. | ||
| */ | ||
| function computeUpdateContentsHash(folderPath: string): string { | ||
| const manifest: string[] = []; | ||
|
|
||
| const walk = (currentPath: string, relativePrefix: string) => { | ||
| for (const entryName of fs.readdirSync(currentPath)) { | ||
| const entryPath = path.join(currentPath, entryName); | ||
| const relativePath = relativePrefix ? `${relativePrefix}/${entryName}` : entryName; | ||
|
|
||
| if (isHashIgnored(relativePath)) { | ||
| continue; | ||
| } | ||
|
|
||
| if (fs.statSync(entryPath).isDirectory()) { | ||
| walk(entryPath, relativePath); | ||
| } else { | ||
| const fileHash = crypto.createHash("sha256").update(fs.readFileSync(entryPath)).digest("hex"); | ||
| manifest.push(`${relativePath}:${fileHash}`); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| walk(folderPath, ""); | ||
| manifest.sort(); | ||
|
|
||
| return crypto.createHash("sha256").update(JSON.stringify(manifest)).digest("hex"); | ||
| } | ||
|
|
||
| ////////////////////////////////////////////////////////////////////////////////////////// | ||
| // Create the platforms to run the tests on. | ||
|
|
||
|
|
@@ -209,6 +177,7 @@ class RNAndroid extends Platform.Android implements RNPlatform { | |
| const string = path.join(innerprojectDirectory, "android", "app", "src", "main", "res", "values", "strings.xml"); | ||
| TestUtil.replaceString(string, TestUtil.SERVER_URL_PLACEHOLDER, this.getServerUrl()); | ||
| TestUtil.replaceString(string, TestUtil.ANDROID_KEY_PLACEHOLDER, this.getDefaultDeploymentKey()); | ||
| TestUtil.replaceString(string, "</resources>", `<string moduleConfig="true" name="CodePushPublicKey">${codeSigningPublicKey}</string>\n</resources>`); | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
| TestUtil.replaceString(AndroidManifest, "\\${usesCleartextTraffic}", "true"); | ||
|
|
||
|
|
||
|
|
@@ -280,14 +249,10 @@ class RNIOS extends Platform.IOS implements RNPlatform { | |
| // Install the Podfile | ||
| return TestUtil.copyFile(path.join(TestConfig.templatePath, "ios", "Podfile"), podfilePath, true) | ||
| .then(() => TestUtil.getProcessOutput(`pod install`, { cwd: iOSProject, noLogStdOut: true })) | ||
| // Put the IOS deployment key in the Info.plist | ||
| .then(TestUtil.replaceString.bind(undefined, infoPlistPath, | ||
| "</dict>\n</plist>", | ||
| "<key>CodePushDeploymentKey</key>\n\t<string>" + this.getDefaultDeploymentKey() + "</string>\n\t<key>CodePushServerURL</key>\n\t<string>" + this.getServerUrl() + "</string>\n\t</dict>\n</plist>")) | ||
| // Set the app version to 1.0.0 instead of 1.0 in the Info.plist | ||
| .then(TestUtil.replaceString.bind(undefined, infoPlistPath, "1.0", "1.0.0")) | ||
| // Remove dependence of CFBundleShortVersionString from project.pbxproj | ||
| .then(TestUtil.replaceString.bind(undefined, infoPlistPath, "\\$\\(MARKETING_VERSION\\)", "1.0.0")) | ||
| .then(() => setPlistStringValue(infoPlistPath, "CFBundleShortVersionString", "1.0.0")) | ||
| .then(() => setPlistStringValue(infoPlistPath, "CodePushDeploymentKey", this.getDefaultDeploymentKey())) | ||
| .then(() => setPlistStringValue(infoPlistPath, "CodePushServerURL", this.getServerUrl())) | ||
| .then(() => setPlistStringValue(infoPlistPath, "CodePushPublicKey", codeSigningPublicKey)) | ||
| // Fix the linker flag list in project.pbxproj (pod install adds an extra comma) | ||
| .then(TestUtil.replaceString.bind(undefined, path.join(iOSProject, TestConfig.TestAppName + ".xcodeproj", "project.pbxproj"), | ||
| "\"[$][(]inherited[)]\",\\s*[)];", "\"$(inherited)\"\n\t\t\t\t);")) | ||
|
|
@@ -440,6 +405,12 @@ class RNProjectManager extends ProjectManager { | |
| return TestUtil.getProcessOutput(`npx create-expo-app@latest ${appName} --template blank@sdk-57`, { cwd: projectDirectory, timeout: 30 * 60 * 1000, noLogStdOut: true }) | ||
| .then((e) => { console.log(`"npx expo init ${appName}" success. cwd=${projectDirectory}`); return e; }) | ||
| .then(this.copyTemplate.bind(this, templatePath, projectDirectory)) | ||
| .then(() => { | ||
| const appJsonPath = path.join(projectDirectory, TestConfig.TestAppName, "app.json"); | ||
| // app.json is JSON, so the PEM's line breaks must stay escaped rather than literal. | ||
| const escapedPublicKey = codeSigningPublicKey.replace(/\n/g, "\\n"); | ||
| TestUtil.replaceString(appJsonPath, CODE_SIGNING_PUBLIC_KEY_PLACEHOLDER, escapedPublicKey); | ||
| }) | ||
| .then<void>(TestUtil.getProcessOutput.bind(undefined, TestConfig.thisPluginInstallString, { cwd: path.join(projectDirectory, TestConfig.TestAppName), noLogStdOut: true, noLogStdErr: true })) | ||
| .then(installExpoBundleTooling.bind(undefined, path.join(projectDirectory, TestConfig.TestAppName))) | ||
| // create-expo-app's blank template ships without a metro.config.js. react-native-xcode.sh's | ||
|
|
@@ -539,28 +510,19 @@ class RNProjectManager extends ProjectManager { | |
| .then(TestUtil.getProcessOutput.bind(undefined, "npx expo prebuild --platform " + targetPlatform.getName(), { cwd: path.join(projectDirectory, TestConfig.TestAppName), noLogStdOut: true })) | ||
| .then(TestUtil.getProcessOutput.bind(undefined, "npx react-native bundle --entry-file index.js --platform " + targetPlatform.getName() + " --bundle-output " + bundlePath + " --assets-dest " + bundleFolder + " --dev false", | ||
| { cwd: path.join(projectDirectory, TestConfig.TestAppName), noLogStdOut: true })) | ||
| .then(() => signAndRecordUpdateArchive(bundleFolder, isDiff)) | ||
| .then<string>(TestUtil.archiveFolder.bind(undefined, bundleFolder, "", path.join(projectDirectory, TestConfig.TestAppName, "update.zip"), isDiff)) | ||
| .then<string>(this.updateMockPackageHash.bind(this, bundleFolder, isDiff)) | ||
| .then((result) => { console.log(`[TIMING] createUpdateArchive(${projectDirectory}, ${targetPlatform.getName()}) took ${Date.now() - t0}ms`); return result; }); | ||
| } else { | ||
| return deferred.promise | ||
| .then(TestUtil.getProcessOutput.bind(undefined, "npx react-native bundle --entry-file index.js --platform " + targetPlatform.getName() + " --bundle-output " + bundlePath + " --assets-dest " + bundleFolder + " --dev false", | ||
| { cwd: path.join(projectDirectory, TestConfig.TestAppName), noLogStdOut: true })) | ||
| .then(() => signAndRecordUpdateArchive(bundleFolder, isDiff)) | ||
| .then<string>(TestUtil.archiveFolder.bind(undefined, bundleFolder, "", path.join(projectDirectory, TestConfig.TestAppName, "update.zip"), isDiff)) | ||
| .then<string>(this.updateMockPackageHash.bind(this, bundleFolder, isDiff)) | ||
| .then((result) => { console.log(`[TIMING] createUpdateArchive(${projectDirectory}, ${targetPlatform.getName()}) took ${Date.now() - t0}ms`); return result; }); | ||
| } | ||
| } | ||
|
|
||
| // Records the real hash of bundleFolder of an archive, so the mock server can hand back a | ||
| // package_hash that matches what the client's verifyFolderHash integrity check will compute. | ||
| private updateMockPackageHash(bundleFolder: string, isDiff: boolean, archivePath: string): string { | ||
| // TODO(RA-4875): Diff updates clear it instead, since they are poorly implemented in the entire test harness. | ||
| // It's going to be a bigger refactor, so for now we just clear the known package hash to avoid using a stale value in diff tests. | ||
| ServerUtil.setKnownPackageHash(isDiff ? undefined : computeUpdateContentsHash(bundleFolder)); | ||
| return archivePath; | ||
| } | ||
|
|
||
| /** JSON file containing the platforms the plugin is currently installed for. | ||
| * Keys must match targetPlatform.getName()! | ||
| * | ||
|
|
@@ -1050,6 +1012,27 @@ PluginTestingFramework.initializeTests(new RNProjectManager(), supportedTargetPl | |
| }); | ||
| }, ScenarioInstall); | ||
|
|
||
| TestBuilder.describe("#localPackage.install.codeSigning", | ||
| () => { | ||
| TestBuilder.it("localPackage.install.codeSigning.tamperedSignature", false, | ||
| async (done: Mocha.Done) => { | ||
| try { | ||
| ServerUtil.updateResponse = { update_info: ServerUtil.createUpdateResponse(false, targetPlatform) }; | ||
|
|
||
| /* create a normal update, then tamper with its signature after it's been signed */ | ||
| const updatePath = await setupTamperedSignatureUpdateScenario(projectManager, targetPlatform, UpdateNotifyApplicationReady, "Tampered Update"); | ||
| ServerUtil.updatePackagePath = updatePath; | ||
| projectManager.runApplication(TestConfig.testRunDirectory, targetPlatform); | ||
| await ServerUtil.expectTestMessages([ | ||
| ServerUtil.TestMessage.CHECK_UPDATE_AVAILABLE, | ||
| ServerUtil.TestMessage.DOWNLOAD_ERROR]); | ||
| done(); | ||
| } catch (e) { | ||
| done(e); | ||
| } | ||
| }); | ||
| }, ScenarioInstall); | ||
|
|
||
| TestBuilder.describe("#localPackage.install.revert", | ||
| () => { | ||
| TestBuilder.it("localPackage.install.revert.dorevert", false, | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New file, I think it's time to start splitting up that really long
test.ts