diff options
Diffstat (limited to 'addon-sdk/source/bin/node-scripts')
-rw-r--r-- | addon-sdk/source/bin/node-scripts/apply-patch.js | 64 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/test.addons.js | 57 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/test.docs.js | 145 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/test.examples.js | 45 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/test.firefox-bin.js | 37 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/test.ini.js | 68 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/test.modules.js | 28 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/update-ini.js | 141 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/utils.js | 104 | ||||
-rw-r--r-- | addon-sdk/source/bin/node-scripts/words.txt | 11 |
10 files changed, 700 insertions, 0 deletions
diff --git a/addon-sdk/source/bin/node-scripts/apply-patch.js b/addon-sdk/source/bin/node-scripts/apply-patch.js new file mode 100644 index 000000000..31fbf7d31 --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/apply-patch.js @@ -0,0 +1,64 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var path = require("path"); +var cp = require("child_process"); +var fs = require("fs"); +var Promise = require("promise"); +var patcher = require("patch-editor"); +var readParam = require("./utils").readParam; + +var isKeeper = /\/addon-sdk\/source/; + +function apply(options) { + return clean(options).then(function() { + return new Promise(function(resolve) { + var patch = path.resolve(readParam("patch")); + var proc = cp.spawn("git", ["apply", patch]); + proc.stdout.pipe(process.stdout); + proc.stderr.pipe(process.stderr); + proc.on("close", resolve); + }); + }); +} +exports.apply = apply; + +function clean(options) { + return new Promise(function(resolve) { + var patch = path.resolve(readParam("patch")); + if (!patch) { + throw new Error("no --patch was provided."); + } + console.log("Cleaning patch " + patch); + + patcher.getChunks({ patch: patch }).then(function(chunks) { + var keepers = []; + + for (var i = chunks.length - 1; i >= 0; i--) { + var chunk = chunks[i]; + var files = chunk.getFilesChanged(); + + // check if the file changed is related to the addon-sdk/source directory + var keepIt = files.map(function(file) { + return (isKeeper.test(file)); + }).reduce(function(prev, curr) { + return prev || curr; + }, false); + + if (keepIt) { + keepers.push(chunk); + } + } + + var contents = "\n" + keepers.join("\n") + "\n"; + contents = contents.replace(/\/addon-sdk\/source/g, ""); + + fs.writeFileSync(patch, contents, { encoding: "utf8" }); + + console.log("Done cleaning patch."); + }).then(resolve).catch(console.error); + }); +} +exports.clean = clean; diff --git a/addon-sdk/source/bin/node-scripts/test.addons.js b/addon-sdk/source/bin/node-scripts/test.addons.js new file mode 100644 index 000000000..dc7c6dfce --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/test.addons.js @@ -0,0 +1,57 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var utils = require("./utils"); +var path = require("path"); +var fs = require("fs"); +var jpm = utils.run; +var readParam = utils.readParam; +var isDebug = utils.isDebug; + +var addonsPath = path.join(__dirname, "..", "..", "test", "addons"); + +var binary = process.env.JPM_FIREFOX_BINARY || "nightly"; +var filterPattern = readParam("filter"); + +describe("jpm test sdk addons", function () { + fs.readdirSync(addonsPath) + .filter(fileFilter.bind(null, addonsPath)) + .forEach(function (file) { + it(file, function (done) { + var addonPath = path.join(addonsPath, file); + process.chdir(addonPath); + + var options = { cwd: addonPath, env: { JPM_FIREFOX_BINARY: binary }}; + if (process.env.DISPLAY) { + options.env.DISPLAY = process.env.DISPLAY; + } + if (/^e10s/.test(file)) { + options.e10s = true; + } + + jpm("run", options).then(done).catch(done); + }); + }); +}); + +function fileFilter(root, file) { + var matcher = filterPattern && new RegExp(filterPattern); + if (/^(l10n-properties|simple-prefs|page-mod-debugger)/.test(file)) { + return false; + } + + // filter additional add-ons when using debug builds + if (isDebug) { + if (/^(chrome|e10s)/.test(file)) { + return false; + } + } + + if (matcher && !matcher.test(file)) { + return false; + } + var stat = fs.statSync(path.join(root, file)) + return (stat && stat.isDirectory()); +} diff --git a/addon-sdk/source/bin/node-scripts/test.docs.js b/addon-sdk/source/bin/node-scripts/test.docs.js new file mode 100644 index 000000000..e6aef516d --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/test.docs.js @@ -0,0 +1,145 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var createHash = require('crypto').createHash; +var fs = require("fs"); +var fsExtra = require("fs-extra") +var path = require("path"); +var Promise = require("promise"); +var chai = require("chai"); +var expect = chai.expect; +var teacher = require("teacher"); + +var rootURI = path.join(__dirname, "..", ".."); + +// get a list of words that fail spell check but are still acceptable +var NEW_WORDS = fs.readFileSync(path.join(__dirname, "words.txt")).toString().trim().split("\n"); + +var CACHE_PATH = path.join(__dirname, "..", "..", "cache", "spellchecks.json"); + +var CACHE = {}; + +try { + CACHE = JSON.parse(fs.readFileSync(CACHE_PATH).toString()); +} +catch (e) {} + +function md5(str) { + return createHash("md5").update(str).digest("utf8"); +} + +function addCacheHash(hash) { + CACHE[hash] = true; + fsExtra.ensureFileSync(CACHE_PATH); + fsExtra.writeJSONSync(CACHE_PATH, CACHE); +} + +describe("Spell Checking", function () { + it("Spellcheck CONTRIBUTING.md", function (done) { + var readme = path.join(rootURI, "CONTRIBUTING.md"); + + fs.readFile(readme, function (err, data) { + if (err) { + throw err; + } + var text = data.toString(); + var hash = md5(text); + + // skip this test if we know we have done the + // exact same test with positive results before + if (CACHE[hash]) { + expect(CACHE[hash]).to.be.equal(true); + return done(); + } + + teacher.check(text, function(err, data) { + expect(err).to.be.equal(null); + + var results = data || []; + results = results.filter(function(result) { + if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) { + return false; + } + + // ignore anything that starts with a dash + if (result.string[0] == "-") { + return false; + } + + if (!(new RegExp(result.string)).test(text)) { + return false; + } + + return true; + }) + + if (results.length > 0) { + console.log(results); + } + else { + addCacheHash(hash); + } + + expect(results.length).to.be.equal(0); + + setTimeout(done, 500); + }); + }); + }); + + it("Spellcheck README.md", function (done) { + var readme = path.join(rootURI, "README.md"); + + fs.readFile(readme, function (err, data) { + if (err) { + throw err; + } + var text = data.toString(); + var hash = md5(text); + + // skip this test if we know we have done the + // exact same test with positive results before + if (CACHE[hash]) { + expect(CACHE[hash]).to.be.equal(true); + return done(); + } + + teacher.check(text, function(err, data) { + expect(err).to.be.equal(null); + + var results = data || []; + results = results.filter(function(result) { + if (NEW_WORDS.indexOf(result.string.toLowerCase()) != -1) { + return false; + } + + // ignore anything that starts with a dash + if (result.string[0] == "-") { + return false; + } + + // ignore anything that we don't find in the original text, + // for some reason "bootstrap.js" becomes "bootstrapjs". + if (!(new RegExp(result.string)).test(text)) { + return false; + } + + return true; + }) + + if (results.length > 0) { + console.log(results); + } + else { + addCacheHash(hash); + } + + expect(results.length).to.be.equal(0); + + done(); + }); + }); + }); +}); diff --git a/addon-sdk/source/bin/node-scripts/test.examples.js b/addon-sdk/source/bin/node-scripts/test.examples.js new file mode 100644 index 000000000..71f7ee43c --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/test.examples.js @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var utils = require("./utils"); +var path = require("path"); +var fs = require("fs"); +var jpm = utils.run; +var readParam = utils.readParam; + +var examplesPath = path.join(__dirname, "..", "..", "examples"); + +var binary = process.env.JPM_FIREFOX_BINARY || "nightly"; +var filterPattern = readParam("filter"); + +describe("jpm test sdk examples", function () { + fs.readdirSync(examplesPath) + .filter(fileFilter.bind(null, examplesPath)) + .forEach(function (file) { + it(file, function (done) { + var addonPath = path.join(examplesPath, file); + process.chdir(addonPath); + + var options = { cwd: addonPath, env: { JPM_FIREFOX_BINARY: binary }}; + if (process.env.DISPLAY) { + options.env.DISPLAY = process.env.DISPLAY; + } + + jpm("test", options).then(done); + }); + }); +}); + +function fileFilter(root, file) { + var matcher = filterPattern && new RegExp(filterPattern); + if (/^(reading-data)/.test(file)) { + return false; + } + if (matcher && !matcher.test(file)) { + return false; + } + var stat = fs.statSync(path.join(root, file)) + return (stat && stat.isDirectory()); +} diff --git a/addon-sdk/source/bin/node-scripts/test.firefox-bin.js b/addon-sdk/source/bin/node-scripts/test.firefox-bin.js new file mode 100644 index 000000000..2570dae20 --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/test.firefox-bin.js @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var fs = require("fs"); +var Promise = require("promise"); +var chai = require("chai"); +var expect = chai.expect; +var normalizeBinary = require("fx-runner/lib/utils").normalizeBinary; + +//var firefox_binary = process.env["JPM_FIREFOX_BINARY"] || normalizeBinary("nightly"); + +describe("Checking Firefox binary", function () { + + it("using matching fx-runner version with jpm", function () { + var sdkPackageJSON = require("../../package.json"); + var jpmPackageINI = require("jpm/package.json"); + expect(sdkPackageJSON.devDependencies["fx-runner"]).to.be.equal(jpmPackageINI.dependencies["fx-runner"]); + }); + + it("exists", function (done) { + var useEnvVar = new Promise(function(resolve) { + resolve(process.env["JPM_FIREFOX_BINARY"]); + }); + + var firefox_binary = process.env["JPM_FIREFOX_BINARY"] ? useEnvVar : normalizeBinary("nightly"); + firefox_binary.then(function(path) { + expect(path).to.be.ok; + fs.exists(path, function (exists) { + expect(exists).to.be.ok; + done(); + }); + }) + }); + +}); diff --git a/addon-sdk/source/bin/node-scripts/test.ini.js b/addon-sdk/source/bin/node-scripts/test.ini.js new file mode 100644 index 000000000..07bd15d1f --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/test.ini.js @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var fs = require("fs"); +var path = require("path"); +var Promise = require("promise"); +var chai = require("chai"); +var expect = chai.expect; +var ini = require("./update-ini"); + +var addonINI = path.resolve("./test/addons/jetpack-addon.ini"); +var packageINI = path.resolve("./test/jetpack-package.ini"); + +describe("Checking ini files", function () { + + it("Check test/addons/jetpack-addon.ini", function (done) { + + fs.readFile(addonINI, function (err, data) { + if (err) { + throw err; + } + // filter comments + var text = data.toString().split("\n").filter(function(line) { + return !/^\s*#/.test(line); + }).join("\n"); + var expected = ""; + + ini.makeAddonIniContent() + .then(function(contents) { + expected = contents; + + setTimeout(function end() { + expect(text.trim()).to.be.equal(expected.trim()); + done(); + }); + }); + }); + + }); + + it("Check test/jetpack-package.ini", function (done) { + + fs.readFile(packageINI, function (err, data) { + if (err) { + throw err; + } + // filter comments + var text = data.toString().split("\n").filter(function(line) { + return !/^\s*#/.test(line); + }).join("\n"); + var expected = ""; + + ini.makePackageIniContent() + .then(function(contents) { + expected = contents; + + setTimeout(function end() { + expect(text.trim()).to.be.equal(expected.trim()); + done(); + }); + }); + }); + + }); + +}); diff --git a/addon-sdk/source/bin/node-scripts/test.modules.js b/addon-sdk/source/bin/node-scripts/test.modules.js new file mode 100644 index 000000000..eb400a5f3 --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/test.modules.js @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var utils = require("./utils"); +var readParam = utils.readParam; +var path = require("path"); +var fs = require("fs"); +var jpm = utils.run; +var sdk = path.join(__dirname, "..", ".."); +var binary = process.env.JPM_FIREFOX_BINARY || "nightly"; + +var filterPattern = readParam("filter"); + +describe("jpm test sdk modules", function () { + it("SDK Modules", function (done) { + process.chdir(sdk); + + var options = { cwd: sdk, env: { JPM_FIREFOX_BINARY: binary } }; + if (process.env.DISPLAY) { + options.env.DISPLAY = process.env.DISPLAY; + } + options.filter = filterPattern; + + jpm("test", options, process).then(done); + }); +}); diff --git a/addon-sdk/source/bin/node-scripts/update-ini.js b/addon-sdk/source/bin/node-scripts/update-ini.js new file mode 100644 index 000000000..634cbc1de --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/update-ini.js @@ -0,0 +1,141 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var path = require("path"); +var cp = require("child_process"); +var fs = require("fs"); +var Promise = require("promise"); +var parser = require("ini-parser"); + +var addonINI = path.resolve("./test/addons/jetpack-addon.ini"); +var addonsDir = path.resolve("./test/addons/"); +var packageINI = path.resolve("./test/jetpack-package.ini"); +var packageDir = path.resolve("./test/"); +var packageIgnorables = [ "addons", "preferences" ]; +var packageSupportFiles = [ + "fixtures.js", + "test-context-menu.html", + "util.js" +] + +function updateAddonINI() { + return new Promise(function(resolve) { + console.log("Start updating " + addonINI); + + makeAddonIniContent(). + then(function(contents) { + fs.writeFileSync(addonINI, contents, { encoding: "utf8" }); + console.log("Done updating " + addonINI); + resolve(); + }); + }) +} +exports.updateAddonINI = updateAddonINI; + +function makeAddonIniContent() { + return new Promise(function(resolve) { + var data = parser.parse(fs.readFileSync(addonINI, { encoding: "utf8" }).toString()); + var result = {}; + + fs.readdir(addonsDir, function(err, files) { + // get a list of folders + var folders = files.filter(function(file) { + return fs.statSync(path.resolve(addonsDir, file)).isDirectory(); + }).sort(); + + // copy any related data from the existing ini + folders.forEach(function(folder) { + var oldData = data[folder + ".xpi"]; + result[folder] = oldData ? oldData : {}; + }); + + // build a new ini file + var contents = []; + Object.keys(result).sort().forEach(function(key) { + contents.push("[" + key + ".xpi]"); + Object.keys(result[key]).forEach(function(dataKey) { + contents.push(dataKey + " = " + result[key][dataKey]); + }); + }); + contents = contents.join("\n") + "\n"; + + return resolve(contents); + }); + }); +} +exports.makeAddonIniContent = makeAddonIniContent; + +function makePackageIniContent() { + return new Promise(function(resolve) { + var data = parser.parse(fs.readFileSync(packageINI, { encoding: "utf8" }).toString()); + var result = {}; + + fs.readdir(packageDir, function(err, files) { + // get a list of folders + var folders = files.filter(function(file) { + var ignore = (packageIgnorables.indexOf(file) >= 0); + var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory(); + return (isDir && !ignore); + }).sort(); + + // get a list of "test-"" files + var files = files.filter(function(file) { + var ignore = !/^test\-.*\.js$/i.test(file); + var isDir = fs.statSync(path.resolve(packageDir, file)).isDirectory(); + return (!isDir && !ignore); + }).sort(); + + // get a list of the support files + var support_files = packageSupportFiles.map(function(file) { + return " " + file; + }); + folders.forEach(function(folder) { + support_files.push(" " + folder + "/**"); + }); + support_files = support_files.sort(); + + // copy any related data from the existing ini + files.forEach(function(file) { + var oldData = data[file]; + result[file] = oldData ? oldData : {}; + }); + + // build a new ini file + var contents = [ + "[DEFAULT]", + "support-files =" + ]; + support_files.forEach(function(support_file) { + contents.push(support_file); + }); + contents.push(""); + + Object.keys(result).sort().forEach(function(key) { + contents.push("[" + key + "]"); + Object.keys(result[key]).forEach(function(dataKey) { + contents.push(dataKey + " = " + result[key][dataKey]); + }); + }); + contents = contents.join("\n") + "\n"; + + return resolve(contents); + }); + }); +} +exports.makePackageIniContent = makePackageIniContent; + +function updatePackageINI() { + return new Promise(function(resolve) { + console.log("Start updating " + packageINI); + + makeAddonIniContent(). + then(function(contents) { + fs.writeFileSync(packageINI, contents, { encoding: "utf8" }); + console.log("Done updating " + packageINI); + resolve(); + }); + }) +} +exports.updatePackageINI = updatePackageINI; diff --git a/addon-sdk/source/bin/node-scripts/utils.js b/addon-sdk/source/bin/node-scripts/utils.js new file mode 100644 index 000000000..1d7f94474 --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/utils.js @@ -0,0 +1,104 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var _ = require("lodash"); +var path = require("path"); +var child_process = require("child_process"); +var jpm = require.resolve("../../node_modules/jpm/bin/jpm"); +var Promise = require("promise"); +var chai = require("chai"); +var expect = chai.expect; +var assert = chai.assert; +var DEFAULT_PROCESS = process; + +var sdk = path.join(__dirname, "..", ".."); +var prefsPath = path.join(sdk, "test", "preferences", "test-preferences.js"); +var e10sPrefsPath = path.join(sdk, "test", "preferences", "test-e10s-preferences.js"); + +var OUTPUT_FILTERS = [ + /[^\n\r]+WARNING\: NS_ENSURE_SUCCESS\(rv, rv\) failed[^\n]+\n\r?/ +]; + +var isDebug = (process.env["JPM_FX_DEBUG"] == "1"); +exports.isDebug = isDebug; + +function spawn (cmd, options) { + options = options || {}; + var env = _.extend({}, options.env, process.env); + + if (isDebug) { + env["MOZ_QUIET"] = 1; + } + + var e10s = options.e10s || false; + + return child_process.spawn("node", [ + jpm, cmd, "-v", "--tbpl", + "--prefs", e10s ? e10sPrefsPath : prefsPath, + "-o", sdk, + "-f", options.filter || "" + ], { + cwd: options.cwd || tmpOutputDir, + env: env + }); +} +exports.spawn = spawn; + +function run (cmd, options, p) { + return new Promise(function(resolve) { + var output = []; + + var proc = spawn(cmd, options); + proc.stderr.pipe(process.stderr); + proc.stdout.on("data", function (data) { + for (var i = OUTPUT_FILTERS.length - 1; i >= 0; i--) { + if (OUTPUT_FILTERS[i].test(data)) { + return null; + } + } + output.push(data); + return null; + }); + + if (p) { + proc.stdout.pipe(p.stdout); + } + else if (!isDebug) { + proc.stdout.pipe(DEFAULT_PROCESS.stdout); + } + else { + proc.stdout.on("data", function (data) { + data = (data || "") + ""; + if (/TEST-/.test(data)) { + DEFAULT_PROCESS.stdout.write(data.replace(/[\s\n]+$/, "") + "\n"); + } + }); + } + + proc.on("close", function(code) { + var out = output.join(""); + var buildDisplayed = /Build \d+/.test(out); + var noTests = /No tests were run/.test(out); + var hasSuccess = /All tests passed!/.test(out); + var hasFailure = /There were test failures\.\.\./.test(out); + if (noTests || hasFailure || !hasSuccess || code != 0) { + DEFAULT_PROCESS.stdout.write(out); + } + expect(code).to.equal(hasFailure ? 1 : 0); + expect(buildDisplayed).to.equal(true); + expect(hasFailure).to.equal(false); + expect(hasSuccess).to.equal(true); + expect(noTests).to.equal(false); + resolve(); + }); + }); +} +exports.run = run; + +function readParam(name) { + var index = process.argv.indexOf("--" + name) + return index >= 0 && process.argv[index + 1] +} +exports.readParam = readParam; diff --git a/addon-sdk/source/bin/node-scripts/words.txt b/addon-sdk/source/bin/node-scripts/words.txt new file mode 100644 index 000000000..b5b29f74b --- /dev/null +++ b/addon-sdk/source/bin/node-scripts/words.txt @@ -0,0 +1,11 @@ +addon-sdk +github +stackoverflow +bugzilla +irc +jsantell +mossop +gozala +zer0 +autonome +0c0w3 |