mirror of
https://github.com/openstf/stf
synced 2025-10-04 10:19:30 +02:00
185 lines
4.7 KiB
JavaScript
185 lines
4.7 KiB
JavaScript
var util = require('util')
|
|
|
|
var split = require('split')
|
|
var Promise = require('bluebird')
|
|
var semver = require('semver')
|
|
var minimatch = require('minimatch')
|
|
|
|
var wire = require('../wire')
|
|
var pathutil = require('./pathutil')
|
|
|
|
var devutil = module.exports = Object.create(null)
|
|
|
|
devutil.matchesRequirements = function(capabilities, requirements) {
|
|
return requirements.every(function(req) {
|
|
var capability = capabilities[req.name]
|
|
|
|
if (!capability) {
|
|
return false
|
|
}
|
|
|
|
switch (req.type) {
|
|
case wire.RequirementType.SEMVER:
|
|
if (!semver.satisfies(capability, req.value)) {
|
|
return false
|
|
}
|
|
break
|
|
case wire.RequirementType.GLOB:
|
|
if (!minimatch(capability, req.value)) {
|
|
return false
|
|
}
|
|
break
|
|
case wire.RequirementType.EXACT:
|
|
if (capability !== req.value) {
|
|
return false
|
|
}
|
|
break
|
|
default:
|
|
return false
|
|
}
|
|
|
|
return true
|
|
})
|
|
}
|
|
|
|
devutil.vendorFiles = function(identity) {
|
|
return {
|
|
bin: {
|
|
src: pathutil.vendor(util.format(
|
|
'remote/libs/%s/remote', identity.abi))
|
|
, dest: '/data/local/tmp/remote'
|
|
, comm: 'remote'
|
|
, mode: 0755
|
|
}
|
|
, lib: {
|
|
src: pathutil.vendor(util.format(
|
|
'remote/external/android-%d/remote_external.so', identity.sdk))
|
|
, dest: '/data/local/tmp/remote_external.so'
|
|
, mode: 0755
|
|
}
|
|
}
|
|
}
|
|
|
|
devutil.ensureUnusedPort = function(adb, serial, port) {
|
|
function closedError(err) {
|
|
return err.message === 'closed'
|
|
}
|
|
return adb.openTcpAsync(serial, port)
|
|
.then(function(conn) {
|
|
conn.end()
|
|
throw new Error(util.format('Port "%d" should be unused', port))
|
|
})
|
|
.catch(closedError, function(err) {
|
|
return Promise.resolve(port)
|
|
})
|
|
}
|
|
|
|
devutil.waitForPort = function(adb, serial, port) {
|
|
function closedError(err) {
|
|
return err.message === 'closed'
|
|
}
|
|
return adb.openTcpAsync(serial, port)
|
|
.then(function(conn) {
|
|
conn.port = port
|
|
return conn
|
|
})
|
|
.catch(closedError, function(err) {
|
|
return Promise.delay(100)
|
|
.then(function() {
|
|
return devutil.waitForPort(adb, serial, port)
|
|
})
|
|
})
|
|
}
|
|
|
|
devutil.listPidsByComm = function(adb, serial, comm, bin) {
|
|
return adb.shellAsync(serial, ['ps', comm])
|
|
.then(function(out) {
|
|
return new Promise(function(resolve, reject) {
|
|
var header = false
|
|
, pids = []
|
|
out.pipe(split())
|
|
.on('data', function(chunk) {
|
|
if (header) {
|
|
header = false
|
|
}
|
|
else {
|
|
var cols = chunk.toString().split(/\s+/)
|
|
if (cols.pop() === bin) {
|
|
pids.push(+cols[1])
|
|
}
|
|
}
|
|
})
|
|
.on('end', function() {
|
|
resolve(pids)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
devutil.waitForProcsToDie = function(adb, serial, comm, bin) {
|
|
return devutil.listPidsByComm(adb, serial, comm, bin)
|
|
.then(function(pids) {
|
|
if (pids.length) {
|
|
return Promise.delay(100)
|
|
.then(function() {
|
|
return devutil.waitForProcsToDie(adb, serial, comm, bin)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
devutil.killProcsByComm = function(adb, serial, comm, bin, mode) {
|
|
return devutil.listPidsByComm(adb, serial, comm, bin, mode)
|
|
.then(function(pids) {
|
|
if (!pids.length) {
|
|
return Promise.resolve()
|
|
}
|
|
return adb.shellAsync(serial, ['kill', mode || -15].concat(pids))
|
|
.then(function(out) {
|
|
return new Promise(function(resolve, reject) {
|
|
out.on('end', resolve)
|
|
})
|
|
})
|
|
.then(function() {
|
|
return devutil.waitForProcsToDie(adb, serial, comm, bin)
|
|
})
|
|
.timeout(2000)
|
|
.catch(function() {
|
|
return devutil.killProcsByComm(adb, serial, comm, bin, -9)
|
|
})
|
|
})
|
|
}
|
|
|
|
devutil.makeIdentity = function(serial, properties) {
|
|
var model = properties['ro.product.model']
|
|
, brand = properties['ro.product.brand']
|
|
, manufacturer = properties['ro.product.manufacturer']
|
|
, operator = properties['gsm.sim.operator.alpha']
|
|
, version = properties['ro.build.version.release']
|
|
, sdk = properties['ro.build.version.sdk']
|
|
, abi = properties['ro.product.cpu.abi']
|
|
|
|
// Remove brand prefix for consistency
|
|
if (model.substr(0, brand.length) === brand) {
|
|
model = model.substr(brand.length)
|
|
}
|
|
|
|
// Remove manufacturer prefix for consistency
|
|
if (model.substr(0, manufacturer.length) === manufacturer) {
|
|
model = model.substr(manufacturer.length)
|
|
}
|
|
|
|
// Clean up remaining model name
|
|
// model = model.replace(/[_ ]/g, '')
|
|
|
|
return {
|
|
serial: serial
|
|
, platform: 'Android'
|
|
, manufacturer: manufacturer.toUpperCase()
|
|
, operator: operator || null
|
|
, model: model
|
|
, version: version
|
|
, abi: abi
|
|
, sdk: sdk
|
|
}
|
|
}
|