Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
473 changes: 0 additions & 473 deletions lib/units/device/plugins/touch/index.js

This file was deleted.

642 changes: 642 additions & 0 deletions lib/units/device/plugins/touch/index.ts

Large diffs are not rendered by default.

75 changes: 0 additions & 75 deletions lib/units/device/resources/minitouch.js

This file was deleted.

96 changes: 96 additions & 0 deletions lib/units/device/resources/minitouch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import util from 'util'
import fs from 'fs'
import syrup from '@devicefarmer/stf-syrup'
import type {Client} from '@u4/adbkit'
import logger from '../../../util/logger.js'
import * as pathutil from '../../../util/pathutil.cjs'
import devutil from '../../../util/devutil.js'
import Resource from './util/resource.js'
import adb from '../support/adb.js'
import abi from '../support/abi.js'
import lifecycle from '../../../util/lifecycle.js'

interface MinitouchOptions {
serial: string
}

interface MinitouchResource {
bin: Resource
}

interface MinitouchResult {
bin: string
run: (cmd?: string) => Promise<NodeJS.ReadableStream>
}

export default syrup.serial()
.dependency(adb)
.dependency(abi)
.dependency(devutil)
.define(async (options: MinitouchOptions, adb: Client, abi: any, devutil: any): Promise<MinitouchResult> => {
const log = logger.createLogger('device:resources:minitouch')
const resources: MinitouchResource = {
bin: new Resource({
src: pathutil.requiredMatch(abi.all.map((supportedAbi: string) =>
pathutil.module(util.format('@devicefarmer/minitouch-prebuilt/prebuilt/%s/bin/minitouch%s', supportedAbi, abi.pie ? '' : '-nopie'))
)),
dest: [
'/data/local/tmp/minitouch',
'/data/data/com.android.shell/minitouch'
],
comm: 'minitouch',
mode: 0o755
})
}

const removeResource = async (res: Resource) => {
await adb.getDevice(options.serial).execOut(['rm', '-f', res.dest])
}

const pushResource = async (res: Resource) => {
const transfer = await adb.getDevice(options.serial).push(res.src, res.dest, res.mode)
await transfer.waitForEnd()
}

const checkExecutable = async (res: Resource) => {
const stats = await adb.getDevice(options.serial).stat(res.dest)
return (stats.mode & fs.constants.S_IXUSR) === fs.constants.S_IXUSR
}

const installResource = async (res: Resource): Promise<void> => {
if (await checkExecutable(res)) return;

log.info('Installing "%s" as "%s"', res.src, res.dest)

await removeResource(res)
await pushResource(res)
const ok = await checkExecutable(res)

if (!ok) {
log.error('Pushed "%s" not executable, attempting fallback location', res.comm)
res.shift()
return installResource(res)
}
}

const plugin = {
bin: resources.bin.dest,
run: (cmd?: string) =>
adb.getDevice(options.serial).shell(`exec ${resources.bin.dest} ${cmd || ''}`),

stop: async () => {
const pid = (await adb.getDevice(options.serial).execOut('pidof minitouch')).toString().trim()
if (!pid?.length) return;

log.info('Stopping minitouch process %s', pid)
return adb.getDevice(options.serial).execOut(['kill', '-9', pid])
}
}

lifecycle.observe(() => plugin.stop())

await plugin.stop()
await installResource(resources.bin)

return plugin
})
3 changes: 1 addition & 2 deletions lib/units/ios-device/plugins/install.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {v4 as uuidv4} from 'uuid'
import syrup from '@devicefarmer/stf-syrup'
import logger from '../../../util/logger.js'
import wire from '../../../wire/index.js'
import wireutil from '../../../wire/util.js'
import Promise from 'bluebird'
import {exec} from 'child_process'
Expand All @@ -10,7 +9,7 @@ import router from '../../base-device/support/router.js'
import push from '../../base-device/support/push.js'
import storage from '../../base-device/support/storage.js'
import deviceutil from '../../../util/deviceutil.js'
import {InstallMessage} from '../../../wire/wire.js'
import {InstallMessage, UninstallIosMessage} from '../../../wire/wire.js'

function execShellCommand(cmd) {
return new Promise((resolve, reject) => {
Expand Down
25 changes: 0 additions & 25 deletions lib/util/failcounter.js

This file was deleted.

31 changes: 31 additions & 0 deletions lib/util/failcounter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import EventEmitter from 'events'

class FailCounter extends EventEmitter {
private threshold: number
private time: number
private values: number[] = []

constructor(threshold: number, time: number) {
super()
this.threshold = threshold
this.time = time
}

inc(): void {
const now = Date.now()
while (this.values.length) {
if (now - this.values[0] >= this.time) {
this.values.shift()
} else {
break
}
}
this.values.push(now)
if (this.values.length > this.threshold) {
this.emit('exceedLimit', this.threshold, this.time)
}
}
}

export default FailCounter

46 changes: 0 additions & 46 deletions lib/util/riskystream.js

This file was deleted.

56 changes: 56 additions & 0 deletions lib/util/riskystream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import EventEmitter from 'events'

class RiskyStream extends EventEmitter {
stream: NodeJS.ReadableStream | NodeJS.WritableStream | any
expectingEnd: boolean = false
ended: boolean = false
private endListener: () => void

constructor(stream: NodeJS.ReadableStream | NodeJS.WritableStream | any) {
super()

this.endListener = () => {
this.ended = true
this.stream.removeListener('end', this.endListener)
if (!this.expectingEnd) {
this.emit('unexpectedEnd')
}
this.emit('end')
}

this.stream = stream.on('end', this.endListener)
}

end(): any {
this.expectEnd()
return this.stream.end()
}

expectEnd(): this {
this.expectingEnd = true
return this
}

async waitForEnd(): Promise<boolean> {
const stream = this.stream
this.expectEnd()

return new Promise<boolean>((resolve) => {
if (stream.ended) {
return resolve(true)
}

const endListener = () => {
stream.removeListener('end', endListener)
resolve(true)
}

stream.on('end', endListener)
// Make sure we actually have a chance to get the 'end' event.
stream.resume()
})
}
}

export default RiskyStream

Loading