mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
425 lines
12 KiB
Java
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?");
|
|
}
|
|
}
|