Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 var childProcess = require("child_process"); | |
| 6 var fs = require("fs"); | |
| 7 var path = require("path"); | |
| 8 var shell = require("child_process").execSync; | |
| 9 | |
| 10 var utils = require("./utils"); | |
| 11 | |
| 12 var Flags = { | |
| 13 BUILD_ONLY: "--build-only", | |
| 14 DEBUG_DEVTOOLS: "--debug-devtools", | |
| 15 TEST_ONLY: "--test-only", | |
| 16 }; | |
| 17 | |
| 18 var IS_DEBUG_ENABLED = utils.includes(process.argv, Flags.DEBUG_DEVTOOLS); | |
| 19 var IS_BUILD_ONLY = utils.includes(process.argv, Flags.BUILD_ONLY); | |
| 20 var IS_TEST_ONLY = utils.includes(process.argv, Flags.TEST_ONLY); | |
| 21 | |
| 22 var CONTENT_SHELL_ZIP = "content-shell.zip"; | |
| 23 var MAX_CONTENT_SHELLS = 10; | |
| 24 var PLATFORM = getPlatform(); | |
| 25 var PYTHON = process.platform === "win32" ? "python.bat" : "python"; | |
| 26 | |
| 27 var BLINK_TEST_PATH = path.resolve(__dirname, "..", "..", "..", "..", "..", "bli nk", "tools", "run_layout_tests.py"); | |
| 28 var CACHE_PATH = path.resolve(__dirname, "..", ".test_cache"); | |
| 29 var SOURCE_PATH = path.resolve(__dirname, "..", "front_end"); | |
| 30 | |
| 31 function main(){ | |
| 32 if (IS_TEST_ONLY) { | |
| 33 findPreviousUploadedPosition(findMostRecentChromiumCommit()) | |
| 34 .then(commitPosition => runTests(path.resolve(CACHE_PATH, commitPosi tion, "out"))); | |
| 35 return; | |
| 36 } | |
| 37 if (!utils.isDir(CACHE_PATH)) | |
| 38 fs.mkdirSync(CACHE_PATH); | |
| 39 deleteOldContentShells(); | |
| 40 findPreviousUploadedPosition(findMostRecentChromiumCommit()) | |
| 41 .then(onUploadedCommitPosition) | |
| 42 .catch(onError); | |
| 43 | |
| 44 function onError(error) { | |
| 45 console.log("Unable to run tests because of error:", error); | |
| 46 console.log(`Try removing the .test_cache folder [${CACHE_PATH}] and ret rying`); | |
| 47 } | |
| 48 } | |
| 49 main(); | |
| 50 | |
| 51 function onUploadedCommitPosition(commitPosition) | |
| 52 { | |
| 53 var contentShellDirPath = path.resolve(CACHE_PATH, commitPosition, "out", "R elease"); | |
| 54 var hasCachedContentShell = utils.isFile(getContentShellBinaryPath(contentSh ellDirPath)); | |
| 55 if (hasCachedContentShell) { | |
| 56 var contentShellPath = path.resolve(CACHE_PATH, commitPosition, "out"); | |
| 57 console.log(`Using cached content shell at: ${contentShellPath}`); | |
| 58 return buildAndTest(contentShellPath); | |
| 59 } | |
| 60 return prepareContentShellDirectory(commitPosition) | |
| 61 .then(downloadContentShell) | |
| 62 .then(extractContentShell) | |
| 63 .then(buildAndTest); | |
| 64 } | |
| 65 | |
| 66 function getPlatform() | |
| 67 { | |
| 68 if (process.platform === "linux") { | |
| 69 if (process.arch === "x64") | |
| 70 return "Linux_x64"; | |
| 71 throw new Error("Pre-compiled content shells are only available for x64 on Linux"); | |
| 72 } | |
| 73 if (process.platform === "win32") { | |
| 74 if (process.arch === "x64") | |
| 75 return "Win_x64"; | |
| 76 return "Win"; | |
| 77 } | |
| 78 if (process.platform === "darwin") { | |
| 79 return "Mac"; | |
| 80 } | |
| 81 throw new Error(`Unrecognized platform detected: ${process.platform}`); | |
| 82 } | |
| 83 | |
| 84 function findMostRecentChromiumCommit() | |
| 85 { | |
| 86 var commitMessage = shell(`git log --max-count=1 --grep="Cr-Commit-Position" `).toString().trim(); | |
| 87 var commitPosition = commitMessage.match(/Cr-Commit-Position: refs\/heads\/m aster@\{#([0-9]+)\}/)[1]; | |
| 88 return commitPosition; | |
| 89 } | |
| 90 | |
| 91 function deleteOldContentShells() | |
| 92 { | |
| 93 var files = fs.readdirSync(CACHE_PATH); | |
| 94 if (files.length < MAX_CONTENT_SHELLS) | |
| 95 return; | |
| 96 files.sort((a, b) => parseInt(b, 10) - parseInt(a, 10)); | |
| 97 var remainingNumberOfContentShells = MAX_CONTENT_SHELLS / 2; | |
| 98 var oldContentShellDirs = files.slice(remainingNumberOfContentShells); | |
| 99 for (var i = 0; i < oldContentShellDirs.length; i++) | |
| 100 utils.removeRecursive(path.resolve(CACHE_PATH, oldContentShellDirs[i])); | |
| 101 console.log(`Removed old content shells: ${oldContentShellDirs}`) | |
| 102 } | |
| 103 | |
| 104 function findPreviousUploadedPosition(commitPosition) | |
| 105 { | |
| 106 var previousPosition = commitPosition - 100; | |
| 107 var positionsListURL = `http://commondatastorage.googleapis.com/chromium-bro wser-snapshots/?delimiter=/&prefix=${PLATFORM}/&marker=${PLATFORM}/${previousPos ition}/`; | |
|
dgozman
2016/10/17 19:13:51
Does one need any permissions for this url?
chenwilliam
2016/10/18 18:13:18
Nope, I was able to download it at home w/ my pers
| |
| 108 return utils.fetch(positionsListURL) | |
| 109 .then(onPositionsList) | |
| 110 .catch(onError); | |
| 111 | |
| 112 function onPositionsList(buffer) | |
| 113 { | |
| 114 var positions = buffer.toString("binary") | |
| 115 .match(/([^<>]+)(?=<\/Prefix><\/CommonPrefixes>)/g) | |
| 116 .map(prefixedPosition => prefixedPosition.split("/")[1]) | |
| 117 .map(positionString => parseInt(positionString, 10)); | |
| 118 var positionSet = new Set(positions); | |
| 119 var previousUploadedPosition = commitPosition; | |
| 120 while (commitPosition - previousUploadedPosition < 100) { | |
| 121 if (positionSet.has(previousUploadedPosition)) | |
| 122 return previousUploadedPosition.toString(); | |
| 123 previousUploadedPosition--; | |
| 124 } | |
| 125 onError(); | |
| 126 } | |
| 127 | |
| 128 function onError(error) | |
| 129 { | |
| 130 if (error) | |
| 131 console.log(`Received error: ${error} trying to fetch positions list from url: ${positionsListURL}`); | |
| 132 throw new Error(`Unable to find a previous upload position for commit po sition: ${commitPosition}`); | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 function prepareContentShellDirectory(contentShellCommitPosition) | |
| 137 { | |
| 138 var contentShellPath = path.join(CACHE_PATH, contentShellCommitPosition); | |
| 139 if (utils.isDir(contentShellPath)) | |
| 140 utils.removeRecursive(contentShellPath); | |
| 141 fs.mkdirSync(contentShellPath); | |
| 142 return Promise.resolve(contentShellCommitPosition); | |
| 143 } | |
| 144 | |
| 145 function downloadContentShell(commitPosition) | |
| 146 { | |
| 147 var url = `http://commondatastorage.googleapis.com/chromium-browser-snapshot s/${PLATFORM}/${commitPosition}/${CONTENT_SHELL_ZIP}`; | |
| 148 console.log("Downloading content shell from:", url); | |
| 149 console.log("NOTE: Download is ~35-65 MB depending on OS"); | |
| 150 return utils.fetch(url) | |
| 151 .then(writeZip) | |
| 152 .catch(onError); | |
| 153 | |
| 154 function writeZip(buffer) | |
| 155 { | |
| 156 console.log("Completed download of content shell"); | |
| 157 var contentShellZipPath = path.join(CACHE_PATH, commitPosition, CONTENT_ SHELL_ZIP); | |
| 158 fs.writeFileSync(contentShellZipPath, buffer); | |
| 159 return contentShellZipPath; | |
| 160 } | |
| 161 | |
| 162 function onError(error) | |
| 163 { | |
| 164 console.log(`Received error: ${error} trying to download content shell f rom url: ${url}`); | |
| 165 throw new Error("Unable to download content shell"); | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 function extractContentShell(contentShellZipPath) | |
| 170 { | |
| 171 console.log(`Extracting content shell zip: ${contentShellZipPath}`); | |
| 172 var unzipScriptPath = path.resolve(__dirname, "unzip.py"); | |
| 173 var src = contentShellZipPath; | |
| 174 var dest = path.resolve(path.dirname(src), "out"); | |
| 175 shell(`${PYTHON} ${unzipScriptPath} ${src} ${dest}`); | |
| 176 fs.unlinkSync(src); | |
| 177 var originalDirPath = path.resolve(dest, "content-shell"); | |
| 178 var newDirPath = path.resolve(dest, "Release"); | |
| 179 fs.renameSync(originalDirPath, newDirPath); | |
| 180 fs.chmodSync(getContentShellBinaryPath(newDirPath), "755"); | |
| 181 if (process.platform === "darwin") { | |
| 182 var helperPath = path.resolve(newDirPath, "Content Shell.app", "Contents ", "Frameworks", "Content Shell Helper.app", "Contents", "MacOS", "Content Shell Helper"); | |
| 183 fs.chmodSync(helperPath, "755"); | |
| 184 } | |
| 185 return dest; | |
| 186 } | |
| 187 | |
| 188 function getContentShellBinaryPath(dirPath) | |
| 189 { | |
| 190 if (process.platform === "linux") { | |
| 191 return path.resolve(dirPath, "content_shell"); | |
| 192 } | |
| 193 if (process.platform === "win32") { | |
| 194 return path.resolve(dirPath, "content_shell.exe"); | |
| 195 } | |
| 196 if (process.platform === "darwin") { | |
| 197 return path.resolve(dirPath, "Content Shell.app", "Contents", "MacOS", " Content Shell"); | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 function buildAndTest(buildDirectoryPath) | |
| 202 { | |
| 203 var contentShellResourcesPath = path.resolve(buildDirectoryPath, "Release", "resources"); | |
| 204 build(contentShellResourcesPath); | |
| 205 if (IS_BUILD_ONLY) | |
| 206 return; | |
| 207 runTests(buildDirectoryPath); | |
| 208 } | |
| 209 | |
| 210 function build(contentShellResourcesPath) | |
| 211 { | |
| 212 var devtoolsResourcesPath = path.resolve(contentShellResourcesPath, "inspect or"); | |
| 213 var copiedFrontendPath = path.resolve(devtoolsResourcesPath, "front_end"); | |
| 214 var debugPath = path.resolve(devtoolsResourcesPath, "debug"); | |
| 215 utils.removeRecursive(copiedFrontendPath); | |
| 216 utils.removeRecursive(debugPath); | |
| 217 utils.copyRecursive(SOURCE_PATH, devtoolsResourcesPath); | |
| 218 fs.renameSync(copiedFrontendPath, debugPath); | |
| 219 var inspectorBackendCommandsPath = path.resolve(devtoolsResourcesPath, "Insp ectorBackendCommands.js"); | |
| 220 var supportedCSSPropertiesPath = path.resolve(devtoolsResourcesPath, "Suppor tedCSSProperties.js"); | |
| 221 utils.copy(inspectorBackendCommandsPath, debugPath); | |
| 222 utils.copy(supportedCSSPropertiesPath, debugPath); | |
| 223 } | |
| 224 | |
| 225 function runTests(buildDirectoryPath) | |
| 226 { | |
| 227 var testArgs = [ | |
| 228 "--additional-drt-flag=--debug-devtools", | |
| 229 "--no-pixel-tests", | |
| 230 "--build-directory", | |
| 231 buildDirectoryPath, | |
| 232 ].concat(getInspectorTests()); | |
| 233 if (IS_DEBUG_ENABLED) { | |
| 234 testArgs.push("--additional-drt-flag=--remote-debugging-port=9222"); | |
| 235 testArgs.push("--time-out-ms=6000000"); | |
| 236 console.log("\n============================================="); | |
| 237 console.log("Go to: http://localhost:9222/"); | |
| 238 console.log("Click on link and in console execute: test()"); | |
| 239 console.log("=============================================\n"); | |
| 240 } | |
| 241 var args = [BLINK_TEST_PATH].concat(testArgs).concat(getTestFlags()); | |
| 242 console.log(`Running layout tests with args: ${args}`); | |
| 243 childProcess.spawn(PYTHON, args, {stdio: "inherit"}); | |
| 244 } | |
| 245 | |
| 246 function getTestFlags() | |
| 247 { | |
| 248 var flagValues = Object.keys(Flags).map(key => Flags[key]); | |
| 249 return process.argv | |
| 250 .slice(2) | |
| 251 .filter(arg => !utils.includes(flagValues, arg) && !utils.includes(arg, "inspector")); | |
| 252 } | |
| 253 | |
| 254 function getInspectorTests() | |
| 255 { | |
| 256 var specificTests = process.argv.filter(arg => utils.includes(arg, "inspecto r")); | |
| 257 if (specificTests.length) | |
| 258 return specificTests; | |
| 259 return [ | |
| 260 "inspector*", | |
| 261 "http/tests/inspector*", | |
| 262 ]; | |
| 263 } | |
| OLD | NEW |