您的位置:首页 > 移动开发 > Android开发

android Monkey测试源码分析之二

2017-04-15 11:28 459 查看

3. 随机运行模式

在上个小节中,monkey有4种运行模式,原理都是一样的,就以随机运行模式为例来论述。

3.1 准备工作

在run方法中,有关随机运行模式代码如下,

mEventSource = new MonkeySourceRandom(mRandom, mMainApps,
mThrottle, mRandomizeThrottle, mPermissionTargetSystem);
mEventSource.setVerbose(mVerbose);
// set any of the factors that has been set
for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) {
if (mFactors[i] <= 0.0f) {
((MonkeySourceRandom) mEventSource).setFactors(i, mFactors[i]);
}
}

// in random mode, we start with a random activity
((MonkeySourceRandom) mEventSource).generateActivity();

首先构造MonkeySourceRandom对象,然后调用其setFactors设置事件的百分比,最后调用generateActivity方法。

MonkeySourceRandom的构造方法如下,

public MonkeySourceRandom(Random random, List<ComponentName> MainApps,
long throttle, boolean randomizeThrottle, boolean permissionTargetSystem) {
// default values for random distributions
// note, these are straight percentages, to match user input (cmd line args)
// but they will be converted to 0..1 values before the main loop runs.
mFactors[FACTOR_TOUCH] = 15.0f; // 为这些事件所占百分比赋初值。
mFactors[FACTOR_MOTION] = 10.0f;
mFactors[FACTOR_TRACKBALL] = 15.0f;
// Adjust the values if we want to enable rotation by default.
mFactors[FACTOR_ROTATION] = 0.0f;
mFactors[FACTOR_NAV] = 25.0f;
mFactors[FACTOR_MAJORNAV] = 15.0f;
mFactors[FACTOR_SYSOPS] = 2.0f;
mFactors[FACTOR_APPSWITCH] = 2.0f;
mFactors[FACTOR_FLIP] = 1.0f;
// disbale permission by default
mFactors[FACTOR_PERMISSION] = 0.0f;
mFactors[FACTOR_ANYTHING] = 13.0f;
mFactors[FACTOR_PINCHZOOM] = 2.0f;

mRandom = random;
mMainApps = MainApps;
// 构造一个MonkeyEventQueue 对象
mQ = new MonkeyEventQueue(random, throttle, randomizeThrottle);
mPermissionUtil = new MonkeyPermissionUtil();
mPermissionUtil.setTargetSystemPackages(permissionTargetSystem);
}
MonkeyEventQueue定义如下,

public class MonkeyEventQueue extends LinkedList<MonkeyEvent> {

private Random mRandom;
private long mThrottle;
private boolean mRandomizeThrottle;

public MonkeyEventQueue(Random random, long throttle, boolean randomizeThrottle) {
super();
mRandom = random;
mThrottle = throttle;
mRandomizeThrottle = randomizeThrottle;
}

@Override
public void addLast(MonkeyEvent e) {
super.add(e);
if (e.isThrottlable()) {
long throttle = mThrottle;
if (mRandomizeThrottle && (mThrottle > 0)) {
throttle = mRandom.nextLong();
if (throttle < 0) {
throttle = -throttle;
}
throttle %= mThrottle;
++throttle;
}
super.add(new MonkeyThrottleEvent(throttle));
}
}
}

MonkeyEventQueue继承于LinkedList,并且仅仅重写了addLast方法。

为了保存各种MonkeyEvent。

setFactors方法重新为所占百分比赋值。

public void setFactors(float factors[]) {
int c = FACTORZ_COUNT;
if (factors.length < c) {
c = factors.length;
}
for (int i = 0; i < c; i++)
mFactors[i] = factors[i];
}

generateActivity方法产生Activity事件。

public void generateActivity() {
MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get(
mRandom.nextInt(mMainApps.size())));
mQ.addLast(e);
}

3.2 测试

MonkeySourceRandom的getNextEvent方法如下,

public MonkeyEvent getNextEvent() {
if (mQ.isEmpty()) {
generateEvents();
}
mEventCount++;
MonkeyEvent e = mQ.getFirst();
mQ.removeFirst();
return e;
}

逻辑很简单,从MonkeyEventQueue中取出下一条事件。如果没有,就产生事件。

generateEvents方法如下,产生各种事件。

private void generateEvents() {
float cls = mRandom.nextFloat();
int lastKey = 0;

if (cls < mFactors[FACTOR_TOUCH]) {
generatePointerEvent(mRandom, GESTURE_TAP);
return;
} else if (cls < mFactors[FACTOR_MOTION]) {
generatePointerEvent(mRandom, GESTURE_DRAG);
return;
} else if (cls < mFactors[FACTOR_PINCHZOOM]) {
generatePointerEvent(mRandom, GESTURE_PINCH_OR_ZOOM);
return;
} else if (cls < mFactors[FACTOR_TRACKBALL]) {
generateTrackballEvent(mRandom);
return;
} else if (cls < mFactors[FACTOR_ROTATION]) {
generateRotationEvent(mRandom);
return;
} else if (cls < mFactors[FACTOR_PERMISSION]) {
mQ.add(mPermissionUtil.generateRandomPermissionEvent(mRandom));
return;
}

// The remaining event categories are injected as key events
for (;;) {
if (cls < mFactors[FACTOR_NAV]) {
lastKey = NAV_KEYS[mRandom.nextInt(NAV_KEYS.length)];
} else if (cls < mFactors[FACTOR_MAJORNAV]) {
lastKey = MAJOR_NAV_KEYS[mRandom.nextInt(MAJOR_NAV_KEYS.length)];
} else if (cls < mFactors[FACTOR_SYSOPS]) {
lastKey = SYS_KEYS[mRandom.nextInt(SYS_KEYS.length)];
} else if (cls < mFactors[FACTOR_APPSWITCH]) {
MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get(
mRandom.nextInt(mMainApps.size())));
mQ.addLast(e);
return;
} else if (cls < mFactors[FACTOR_FLIP]) {
MonkeyFlipEvent e = new MonkeyFlipEvent(mKeyboardOpen);
mKeyboardOpen = !mKeyboardOpen;
mQ.addLast(e);
return;
} else {
lastKey = 1 + mRandom.nextInt(KeyEvent.getMaxKeyCode() - 1);
}

if (lastKey != KeyEvent.KEYCODE_POWER
&& lastKey != KeyEvent.KEYCODE_ENDCALL
&& lastKey != KeyEvent.KEYCODE_SLEEP
&& PHYSICAL_KEY_EXISTS[lastKey]) {
break;
}
}

MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey);
mQ.addLast(e);

e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey);
mQ.addLast(e);
}

runMonkeyCycles使用while循环调用获取MonkeyEvent然后注入事件。

MonkeyEvent ev = mEventSource.getNextEvent();
if (ev != null) {
int injectCode = ev.injectEvent(mWm, mAm, mVerbose);

终止的条件如下,

while (!systemCrashed && cycleCounter < mCount) {

1,系统已经崩溃

2,重复次数已经到了设置次数。

这样很简单就完成测试了。

4. monkey框架结构

Monkey的代码比较少,结构简单。主要功能分为2块

1,产生事件

2,触发事件

Monkey.java

  程序的入口,调度中心,解析参数,构造不同的MonkeyEventSource子类。

MonkeyEventSource.java

  4中模式分别对应不同的MonkeyEventSource

例如, MonkeySourceScript/MonkeySourceRandomScript/ MonkeySourceNetwork/ MonkeySourceRandom

MonkeyEvent.java

  各种事件的具体实现。如MonkeyKeyEvent/ MonkeyMotionEvent等等。

 

最后都是调用AM/WM/PM 来实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息