gecko/build/mobile/robocop/FennecNativeDriver.java.in

425 lines
12 KiB
Java

#filter substitution
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Firefox Mobile Test Framework.
*
* The Initial Developer of the Original Code is Mozilla.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Trevor Fairey <tnfairey@gmail.com>
* David Burns <dburns@mozilla.com>
* Joel Maher <joel.maher@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package @ANDROID_PACKAGE_NAME@;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.HashMap;
import java.util.List;
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.Long;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import org.json.*;
import com.jayway.android.robotium.solo.Solo;
public class FennecNativeDriver implements Driver {
// Map of IDs to element names.
private HashMap locators = null;
private Activity activity;
private Solo solo;
private String logFile;
// Objects for reflexive access of fennec classes.
private ClassLoader classLoader;
private Class gel;
private Class ge;
private Class gas;
private Method registerGEL;
private Method unregisterGEL;
private Method sendGE;
private Method _startFrameRecording;
private Method _stopFrameRecording;
private LinkedList<testInfo> testList = new LinkedList<testInfo>();
public FennecNativeDriver(Activity activity, Solo robocop){
this.activity = activity;
this.solo = robocop;
// Set up table of fennec_ids.
locators = convertTextToTable(getFile("/mnt/sdcard/fennec_ids.txt"));
// Set up reflexive access of java classes and methods.
try {
classLoader = activity.getClassLoader();
gel = classLoader.loadClass("org.mozilla.gecko.GeckoEventListener");
ge = classLoader.loadClass("org.mozilla.gecko.GeckoEvent");
gas = classLoader.loadClass("org.mozilla.gecko.GeckoAppShell");
Class [] parameters = new Class[2];
parameters[0] = String.class;
parameters[1] = gel;
registerGEL = gas.getMethod("registerGeckoEventListener", parameters);
unregisterGEL = gas.getMethod("unregisterGeckoEventListener", parameters);
parameters = new Class[1];
parameters[0] = ge;
sendGE = gas.getMethod("sendEventToGecko", parameters);
Class gfx = classLoader.loadClass("org.mozilla.gecko.gfx.PanningPerfAPI");
_startFrameRecording = gfx.getDeclaredMethod("startFrameTimeRecording");
_stopFrameRecording = gfx.getDeclaredMethod("stopFrameTimeRecording");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
//Information on the location of the Gecko Frame.
private boolean geckoInfo = false;
private int geckoTop = 100;
private int geckoLeft = 0;
private int geckoHeight= 700;
private int geckoWidth = 1024;
private void getGeckoInfo() {
View geckoLayout = activity.findViewById(Integer.decode((String)locators.get("gecko_layout")));
if (geckoLayout != null) {
geckoTop = geckoLayout.getTop();
geckoLeft = geckoLayout.getLeft();
geckoWidth = geckoLayout.getWidth();
geckoHeight = geckoLayout.getHeight();
geckoInfo = true;
}
}
public int getGeckoTop() {
if(!geckoInfo) {
getGeckoInfo();
}
return geckoTop;
}
public int getGeckoLeft() {
if(!geckoInfo) {
getGeckoInfo();
}
return geckoLeft;
}
public int getGeckoHeight() {
if(!geckoInfo) {
getGeckoInfo();
}
return geckoHeight;
}
public int getGeckoWidth() {
if(!geckoInfo) {
getGeckoInfo();
}
return geckoWidth;
}
public Element findElement(Activity activity, String name) {
if (name == null)
throw new IllegalArgumentException("Can not findElements when passed a null");
if (locators.containsKey(name)){
return new FennecNativeElement(Integer.decode((String)locators.get(name)), activity, solo);
}
throw new RoboCopException("Element does not exist in the list");
}
public void startFrameRecording() {
try {
Object [] params = null;
_startFrameRecording.invoke(null, params);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public int stopFrameRecording() {
Class [] parameters = new Class[1];
parameters[0] = null;
List frames;
try {
Object [] params = null;
frames = (List)_stopFrameRecording.invoke(null, params);
Object [] framearray = frames.toArray();
Long last = new Long(0);
Long threshold = new Long(17);
int numDelays = 0;
for (int i=0; i < framearray.length; i++) {
Long val = (Long)framearray[i];
if ((val - last) > threshold) {
numDelays++;
}
last = val;
}
return numDelays;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return 0;
}
class scrollHandler implements InvocationHandler {
public scrollHandler(){};
public Object invoke(Object proxy, Method method, Object[] args) {
try{
//Disect the JSON object into the appropriate variables
JSONObject jo = ((JSONObject)args[1]);
scrollHeight = jo.getInt("y");
height = jo.getInt("cheight");
//We don't want a height of 0. That means it's a bad response.
if( height > 0) {
pageHeight = jo.getInt("height");
}
} catch( Throwable e) {
Log.i("Robocop", "WARNING: ScrollReceived, but read wrong!");
}
return null;
}
}
public int getScrollHeight() {
return scrollHeight;
}
public int getPageHeight() {
return pageHeight;
}
public int getHeight() {
return height;
}
public int height=0;
public int scrollHeight=0;
public int pageHeight=10;
public void setupScrollHandling() {
//Setup scrollHandler to catch "robocop:scroll" events.
try {
Class [] interfaces = new Class[1];
interfaces[0] = gel;
Object[] finalParams = new Object[2];
finalParams[0] = "robocop:scroll";
finalParams[1] = Proxy.newProxyInstance(classLoader, interfaces, new scrollHandler());
registerGEL.invoke(null, finalParams);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
//Takes a filename, loads the file,
// and returns a string version of the entire file.
public static String getFile(String filename)
{
File file = new File(filename);
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
} catch(IOException e) {
e.printStackTrace();
}
return text.toString();
}
// Write information to a logfile and logcat
public void dumpLog(String message)
{
File file = new File(logFile);
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(logFile, true));
bw.write(message);
bw.newLine();
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
if (bw != null) {
bw.flush();
bw.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
Log.i("Robocop", message);
}
// Set the filename used for dumpLog.
public void setLogFile(String filename)
{
logFile = filename;
}
// Takes a string of "key=value" pairs split by \n and creates a hash table.
public static HashMap convertTextToTable(String data)
{
HashMap retVal = new HashMap();
String[] lines = data.split("\n");
for (int i = 0; i < lines.length; i++) {
String[] parts = lines[i].split("=");
retVal.put(parts[0].trim(), parts[1].trim());
}
return retVal;
}
class testInfo {
public boolean result;
public String name;
public String diag;
public boolean todo;
public testInfo(boolean r, String n, String d, boolean t) {
result = r;
name = n;
diag = d;
todo = t;
}
}
private void _logResult(testInfo test, String passString, String failString)
{
boolean isError = true;
String resultString = failString;
if(test.result || test.todo){
isError = false;
}
if(test.result)
{
resultString = passString;
}
String diag= test.name;
if(test.diag!=null) diag+= " - " + test.diag;
String message = resultString + " | " + "ROBOCOP" + " | " + diag;
if(isError) {
dumpLog(message);
}
else {
dumpLog(message);
}
}
public void ok(boolean condition, String name, String diag) {
testInfo test = new testInfo(condition, name, diag, false);
_logResult(test, "TEST-PASS", "TEST-UNEXPECTED-FAIL");
testList.add(test);
}
public void is(Object a, Object b, String name) {
boolean pass = a.equals(b);
String diag = "got " + a.toString() + ", expected " + b.toString();
if(pass) {
diag = a.toString() + " should equal " + b.toString();
}
ok(pass, name, diag);
}
public void isnot(Object a, Object b, String name) {
boolean pass = !a.equals(b);
String diag = "didn't expect " + a.toString() + ", but got it";
if(pass) {
diag = a.toString() + " should not equal " + b.toString();
}
ok(pass, name, diag);
}
public void todo(boolean condition, String name, String diag) {
testInfo test = new testInfo(condition, name, diag, true);
_logResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL");
testList.add(test);
}
public void todo_is(Object a, Object b, String name) {
boolean pass = a.equals(b);
String diag = "got " + a.toString() + ", expected " + b.toString();
if(pass) {
diag = a.toString() + " should equal " + b.toString();
}
todo(pass, name, diag);
}
public void todo_isnot(Object a, Object b, String name) {
boolean pass = !a.equals(b);
String diag = "didn't expect " + a.toString() + ", but got it";
if(pass) {
diag = a.toString() + " should not equal " + b.toString();
}
todo(pass, name, diag);
}
public void info(String name, String message) {
testInfo test = new testInfo(true, name, message, false);
_logResult(test, "TEST-INFO", "INFO FAILED?");
}
}