FEST: Wait for the GUI to load before doing anything - java

#Before public void setUp() {
Robot robot = BasicRobot.robotWithCurrentAwtHierarchy();
ApplicationLauncher.application("myApp").start();
Pause.pause(5, TimeUnit.SECONDS);
frame = WindowFinder.findFrame("frame0").using(robot);
JTableFixture table = frame.table(new GenericTypeMatcher<JTable>(JTable.class) {
#Override protected boolean isMatching(JTable table) {
return (table instanceof myTreeTable);
}
});
}
This code works well. If we remove the 5 seconds pause, then the table is not found because it takes some seconds to the app to load it.
I would like to know if there is a cleaner way of doing it. I tried with robot.waitForIdle() after ApplicationLauncher (I guess once EDT is empty, everything is loaded), but it just doesn´t work.
I know pause can use some conditions as an event on when to stop, but I don´t understand how to write it since JavaDoc and official doc is poor.
Pause.pause(WaitForComponentToShowCondition.untilIsShowing(frame.component())) : I need a component, if I pass the wrapper frame it does not work. And I cannot pass the table because thats precisely what I am waiting for to get.
I understand then I should probably work with ComponentFoundCondition but I dont get it! I tired with:
ComponentMatcher matcher = new GenericTypeMatcher<JTable>(JTable.class) {
#Override protected boolean isMatching(JTable table) {
return (table instanceof myTreeTable);
}
};
Pause.pause(new ComponentFoundCondition("DebugMsg", frame.robot.finder(), matcher));
Any help?

You could use ComponentFinder to locate the component. For example, based on the matcher in the question:
final ComponentMatcher matcher = new TypeMatcher(myTreeTable.class);
Pause.pause(new Condition("Waiting for myTreeTable") {
#Override
public boolean test() {
Collection<Component> list =
window.robot.finder().findAll(window.target, matcher);
return list.size() > 0;
}
}, 5000);
Here is an alternative with lookup by name:
final ComponentMatcher nameMatcher = new ComponentMatcher(){
#Override
public boolean matches(Component c) {
return "ComponentName".equals(c.getName()) && c.isShowing();
}
};
Pause.pause(new Condition("Waiting") {
#Override
public boolean test() {
Collection<Component> list =
window.robot.finder().findAll(window.target, nameMatcher);
return list.size() > 0;
}
}, 5000);

Related

How to kill a Rhino script

We are using Rhino to execute Javascript inside our Java app. We make use of some Rhino-specific features so we can’t upgrade to Nashorn.
The problem we have is that scripts are created by users, and when we execute them, if there is a mistake like an infinite loop, it keeps executing forever. We want to set a time limit of something like 30 seconds.
Is there a way to kill a script when the timeout is hit?
You should extend the ContextFactory class and override the method observeInstructionCount(Context ctx, int instructionCount). This method will be called periodically by Rhino and you can check how long it has been running so far with something like this:
public class ScriptDynamicScopeFactory extends ContextFactory {
#Override
protected Context makeContext() {
ScriptContext ctx = new ScriptContext();
ctx.setInstructionObserverThreshold(10000);
return ctx;
}
#Override
protected void observeInstructionCount(Context ctx, int instructionCount) {
long currentTime = System.currentTimeMillis();
long executionTime = (currentTime - ((ScriptContext) ctx).startTime());
// do something if execution time is greater then your timeout
}
}
Notice that you also need to override makeContext() to set how often your observer will be called. Keep in mind that this is the number of instructions executed, which means that it won't get called consistently every X ms. If one instruction takes a lot (for example, calling your Java app), this might not work well, but I think it will do a good job in almost all cases.
You can stop loop from running by creating a dummy debugger and add it to the javascript directly like this:
mContext = Context.enter();
ObservingDebugger observingDebugger = new ObservingDebugger();
mContext.setDebugger(observingDebugger, new Integer(0));
mContext.setGeneratingDebug(true);
mContext.setOptimizationLevel(-1);
Then through the java program, you create a class that looks like this:
public class ObservingDebugger implements Debugger
{
boolean isDisconnected = false;
private DebugFrame debugFrame = null;
public boolean isDisconnected() {
return isDisconnected;
}
public void setDisconnected(boolean isDisconnected) {
this.isDisconnected = isDisconnected;
if(debugFrame != null){
((ObservingDebugFrame)debugFrame).setDisconnected(isDisconnected);
}
}
public ObservingDebugger() {
}
public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript)
{
if(debugFrame == null){
debugFrame = new ObservingDebugFrame(isDisconnected);
}
return debugFrame;
}
#Override
public void handleCompilationDone(Context arg0, DebuggableScript arg1, String arg2) { } }
// internal ObservingDebugFrame class
class ObservingDebugFrame implements DebugFrame
{
boolean isDisconnected = false;
public boolean isDisconnected() {
return isDisconnected;
}
public void setDisconnected(boolean isDisconnected) {
this.isDisconnected = isDisconnected;
}
ObservingDebugFrame(boolean isDisconnected)
{
this.isDisconnected = isDisconnected;
}
public void onEnter(Context cx, Scriptable activation,
Scriptable thisObj, Object[] args)
{ }
public void onLineChange(Context cx, int lineNumber)
{
if(isDisconnected){
throw new RuntimeException("Script Execution terminaed");
}
}
public void onExceptionThrown(Context cx, Throwable ex)
{ }
public void onExit(Context cx, boolean byThrow,
Object resultOrException)
{ }
#Override
public void onDebuggerStatement(Context arg0) { } }
Then to set the timer of the program, you import:
import java.util.Timer;
Then you set your timer prefernece for the ObservingDebugger:
timer.schedule(new TimerTask() {
#Override
public void run() {
// code here
}
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);

onAccessibilityEvent Action_click Not working

Okay, so I am working on an app that will auto accept lyft request, but I am having a problem with my code not using performAction(AccessibilityNodeInfo.ACTION_CLICK); correctly.
public class AutoService extends AccessibilityService {
private static LyftAdapter lyftAdapter = new LyftAdapter();
// Automated Service (onAccessibilityEvent)
#TargetApi(16)
#Override
public void onAccessibilityEvent(AccessibilityEvent event)
{
AccessibilityNodeInfo source = event.getSource();
String lyftPackage = "com.lyft.android.driver";
String packageName = Tools.getPackage(source);
if (!packageName.equals(lyftPackage))
{
event.recycle();
return;
}
if (source == null)
{
event.recycle();
return;
}
processUI(event.getSource());
}
public void processUI(AccessibilityNodeInfo source)
{
source = getRootInActiveWindow();
if (Tools.getPackage(source).equals("com.lyft.android.driver") || Tools.getPackage(source).equals("me.lyft.android"))
{
if (!Lyft_Status.equals("OFFLINE"))
{
lyftAdapter.processEvent(source);
}
else
{
Log.v(TAG, "Can't process UI: " + Lyft_Status);
}
}
if (source != null)
source.recycle();
}
}
public abstract class RideshareAdapter {
public void processEvent(final AccessibilityNodeInfo source)
{
final StringBuilder sb = new StringBuilder();
processSubEvent(source, 0, sb);
final String string = sb.toString();
if (string == null)
{
Log.v(TAG, "String is NULL");
return;
}
processUIText(source, string.toLowerCase());
}
// PROCESS SECONDARY EVENT
private void processSubEvent(final AccessibilityNodeInfo source, final int n, final StringBuilder sb) {
for (int i = 0; i < n; ++i) {
sb.append("\t");
}
if (source != null)
{
sb.append(Tools.getText(source));
sb.append("\n");
final int childCount = source.getChildCount();
for (int j = 0; j < childCount; ++j) {
final AccessibilityNodeInfo child = source.getChild(j);
processSubEvent(child, n + 1, sb);
if (child != null) {
child.recycle();
}
}
}
}
// CLICK THE SCREEN
protected void clickScreen(AccessibilityNodeInfo source, final String text)
{
final AccessibilityNodeInfo s = source;
new Handler().postDelayed(new Runnable() {
List<AccessibilityNodeInfo> list = s.findAccessibilityNodeInfosByText(text);
#Override
public void run() {
for (final AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}, 1000);
}
}
public class LyftAdapter
extends RideshareAdapter
{
// LYFT ADAPTER
protected void processUIText(AccessibilityNodeInfo source, String text)
{
// RIDE REQUEST
if (text.contains("tap here to accept"))
{
clickScreen(source, "Tap here to accept");
{
}
The string comes out as (Just like it is shown):
Lyft
11 mins
away
Passenger Name
New
Tap here to accept
But for some reason, it triggers saying it is going to click on "Tap here to accept" textview, but it never actually does it. Any suggestions?
To be completely honest, your post is very difficult to read. You have functions that you have defined purely for organizational purposes and not because they are meant to be re-used. It makes it very difficult to parse and understand over the course of a StackOverflow post... Yet you did not provide enough for me to copy and paste and make sense of in Android Studio.
When you post code on StackOverflow you should go for a minimal replicating example and you ABSOLUTELY should remove your random Log calls. You may need them to help you understand what's happening, but hopefully WE do not :) and they just clutter things and make it more difficult to read your code. THIS BEING SAID, allow me to focus on one bit,
Note that I have cleaned up some of the poor style and debugging statements. Answers are in the code comments!
protected void clickScreen(final AccessibilityNodeInfo source, final String text)
{
new Handler().postDelayed(new Runnable() {
//Find ALL of the nodes that match the "text" argument.
List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByText(text);
#Override
public void run() {
//Non discrliminintly click them, whether they're buttons, or text fields or links... just click them and hope they do something.
for (final AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
//Delay it for a second AFTER the function has been called for no particularly good reason besides perhaps invalidating all of the nodes in the heirarchy... GOOD CALL!
}, 1000);
}
Given the above issues and the aforementioned generic code quality issues, it is difficult to provide a concise answer. This post leaves too many potential issues. Any provided answer would be a stab in the dark. I find it MOST likely that the problem is covered in my code comments, but it could most definitely be elsewhere. Also, my apologies for the sass!
All this being said, you might try this version of the function!
static void clickFirstMatchingNode(AccessibilityService service, final String text) {
final List<AccessibilityNodeInfo> list = service.getRootInActiveWindow().findAccessibilityNodeInfosByText(text);
for (AccessibilityNodeInfo node : list) {
//Check if the action completely successfully. Also, only click one of them. This is kind of an assumption, it also simplifies the logic. You can certainly write a version of this that clicks everything that matches!
if (node.performAction(AccessibilityNodeInfo.ACTION_CLICK)) return;
}
//If no node is successfully clicked Log some stuff!
Log.wtf(YourService.class.getName(), "Failed to click any nodes! WTF?: " + text);
}
NOTE: None of the above mentioned anything to do with your use of Accessibility APIs! I think that that is interesting.

Multithreading refresh UI in Vaadin

I'm trying to implement a multithreading refresh UI in my Vaadin app.
Part of this UI is a dChart based on container. To build dChart Im iterating through container and count elements by one of their properties, like this:
Collection<?> itemIDS = container.getItemIds();
for (Object itemID : itemIDS) {
Property property = container.getContainerProperty(itemID, "status");
String status = (String) property.getValue();
if (countMap.containsKey(status)) {
countMap.put(status, countMap.get(status) + 1);
} else {
countMap.put(status, 1);
}
}
However it takes over 2-3 seconds if container has thousands of elements.
User just can't wait so long to refresh an UI.
I read that i can build my UI and later just refresh it using #Push Vaadin annotation, after dChart is fully built.
So i build something like this:
{
//class with #Push
void refreshPieDChart(GeneratedPropertyContainer container) {
new InitializerThread(ui, container).start();
}
class InitializerThread extends Thread {
private LogsUI parentUI;
private GeneratedPropertyContainer container;
InitializerThread(LogsUI ui, GeneratedPropertyContainer container) {
parentUI = ui;
this.container = container;
}
#Override
public void run() {
//building dChart etc etc... which takes over 2-3 seconds
// Init done, update the UI after doing locking
parentUI.access(new Runnable() {
#Override
public void run() {
chart.setDataSeries(dataSeries).show();
}
});
}
}
}
However if i refresh page few times, it is generating errors about SQLContainer:
java.lang.IllegalStateException: A trasaction is already active!
Becouse after few refreshes, my multiple threads are running parallel using the same SQLContainer.
To fix that, I want to stop all working refresh threads except last one to eliminate concurrent problem. How i can do it? Maybe other solution?
EDIT:
I have tried smth like this, but problem still remains, is it a correct way to prevent concurrent problem?
{
private static final Object mutex = new Object();
//class with #Push
void refreshPieDChart(GeneratedPropertyContainer container) {
new InitializerThread(ui, container).start();
}
class InitializerThread extends Thread {
private LogsUI parentUI;
private GeneratedPropertyContainer container;
InitializerThread(LogsUI ui, GeneratedPropertyContainer container) {
parentUI = ui;
this.container = container;
}
#Override
public void run() {
//is it correct way to prevent concurrent problem?
synchronized(mutex){
//method to refresh/build chart which takes 2-3s.
}
// Init done, update the UI after doing locking
parentUI.access(new Runnable() {
#Override
public void run() {
chart.setDataSeries(dataSeries).show();
}
});
}
}
}
This is what i did:
Henri Kerola points me pretty obvious idea: do counting in SQL. As i said I was thinking about that but that would means I need to prepare SQL for every possible filters combination. That is a pretty complicated and doesn't look good.
But this realised me that if I'm using SQLContainer with filters for my table, I can do the same for counting. I just need to create second SQLContainer with my ownFreeformQuery and FreeformStatementDelegate.
If i will create all of above, i can just add THE SAME filters to both containers however i dont need to count elements now becouse 2nd container holds values for me. It sounds complecated but take a look on my code:
FreeformQuery myQuery = new MyFreeformQuery(pool);
FreeformQuery countQuery = new CountMyFreeformQuery(pool);
SQLContainer myContainer = new SQLContainer(myQuery); //here i hold my all records as in a Question
SQLContainer countContainer = new SQLContainer(countQuery); //here i hold computed count(*) and status
MyFreeformQuery.java looks like:
class ProcessFreeformQuery extends FreeformQuery {
private static final String QUERY_STRING = "SELECT request_date, status, id_foo FROM foo";
private static final String COUNT_STRING = "SELECT COUNT(*) FROM foo";
private static final String PK_COLUMN_NAME = "id_foo";
MyFreeformQuery(JDBCConnectionPool connectionPool) {
super(QUERY_STRING, connectionPool, PK_COLUMN_NAME);
setDelegate(new AbstractFreeformStatementDelegate() {
protected String getPkColumnName() {
return PK_COLUMN_NAME;
}
protected String getQueryString() {
return QUERY_STRING;
}
protected String getCountString() {
return COUNT_STRING;
}
});
}
and most important CountFreeformQuery.java looks like:
public class CountFreeformQuery extends FreeformQuery {
private static final String QUERY_STRING_GROUP = "SELECT status, count(*) as num FROM foo GROUP BY status";
private static final String QUERY_STRING = "SELECT status, count(*) as num FROM foo";
private static final String GROUP_BY = "foo.status";
public CountFreeformQuery(JDBCConnectionPool connectionPool) {
super(QUERY_STRING_GROUP, connectionPool);
setDelegate(new CountAbstractFreeformStatementDelegate() {
protected String getQueryString() {
return QUERY_STRING;
}
protected String getGroupBy(){
return GROUP_BY;
}
});
}
}
Now if i want to refresh dChart after smth like that:
myContainer.addContainerFilter(new Between(DATE_PROPERTY, getTimestamp(currentDate), getOneDayAfter(currentDate)));
I just do the same with countContainer:
countContainer.addContainerFilter(new Between(DATE_PROPERTY, getTimestamp(currentDate), getOneDayAfter(currentDate)));
And pass it to method which dont need to count elements, just add all container to map and then to dChart like that:
Map<String, Long> countMap = new HashMap<String, Long>();
Collection<?> itemIDS = container.getItemIds();
for (Object itemID : itemIDS) {
Property statusProperty = container.getContainerProperty(itemID, "status");
Property numProperty = container.getContainerProperty(itemID, "num");
countMap.put((String) statusProperty.getValue(), (Long) numProperty.getValue());
}
Now i have statuses of elements in myContainer counted, no need to multithreading or writing tons of sql.
Thanks guys for suggestions.

Emitting 2 observables, processing the result and then emitting another one

I have the following task to perform:
I need to emit 2 observables (obs1 & obs2) process their results and then call another observable (obs3) and process its results and if possible that while processing the results of obs3 have access to the results of obs1 and obs2.
This is my draft code which doesn't do the trick, how can I alter it.
public void executeFind(String session_id, long template_id, GameModelType game_model) {
Observable<RxMessage<byte[]>> userObs = context.getUser(session_id);
Observable<Game> gameObs = context.findGame(template_id, game_model, GameStateType.WAITING);
Observable.zip(userObs, gameObs, new Func2<RxMessage<byte[]>, Game, GameObject>() {
#Override
public GameObject call(RxMessage<byte[]> userRawReply, ActiveGame game) {
..
..
return context.updateGame(game.getGameData())
.subscribe(new Action1<GameObject>() {
#Override
public void call(GameObject updateReply) {
..
..
}
});
return userReply;
}
});
}
This doesn't really work - I can write a code which uses explicit calls to .flatMap\subscribe for each Observable but results in many nested calls which is obviously poor usage of the framework.
What is the right way to solve this??
Thank you!
EDIT:
I've found this solution to work, but I'm still wondering whether there is a "cleaner" way to achieve this:
public void executeFind(ReplyMessage<JsonObject> replyObj, String session_id, long template_id, GameModelType game_model) throws CommandException {
rx.Observable<GameObject> userObs = context.getUser(session_id);
rx.Observable<Game> gameObs = context.findGame(template_id, game_model, GameStateType.WAITING);
rx.Observable.zip(userObs, gameObs, new Func2<GameObject, Game, List<Object>>() {
#Override
public List<Object> call(GameObject userReply, Game game) {
User user = ...;
final List<Object> results = new ArrayList<Object>(3);
results.add(ErrorCodes.STATUS_OK);
results.add(user);
results.add(game);
context.updateGame(game.getGameData()).subscribe(new Action1<GameObject>() {
#Override
public void call(GameObject updateReply) {
...
}
});
return results;
}
}).subscribe(new Action1<List<Object>>() {
#Override
public void call(List<Object> results) {
int status = (int) results.get(0);
User user = (User) results.get(1);
Game game = (Game) results.get(2);
}
});
}
I would code this thing with the following idea in mind. May be map can be replace with flatMap if that's relevant for your use case. Also note I have only used Java 8 lambdas syntax, but for more readability I strongly advises you to have simple and well named methods (and use them with a method reference) for each of these functions/actions as it will raise understandability of the code (That's what we do on mockito, but everyone should do it in their own code base).
public void executeFind(ReplyMessage<JsonObject> reply_obj, String session_id, long template_id, GameModelType game_model) throws CommandException {
Observable<GameObject> userObs = context.getUser(session_id);
Observable<Game> gameObs = context.findGame(template_id, game_model, GameStateType.WAITING);
Observable.zip(userObs, gameObs, (userReply, game) -> {
User user = ...;
return GameOfUser.gameFound(game, user);
}).map(gou -> {
context.updateGame(gou.gameData()).susbcribe(...);
return gou;
}).subscribe(gou -> ...);
}

How to return String in anonymous class for a method returning void

I'm bit confused. I have the following:
public static String showInputDialog() {
Form frm = new Form();
final Command cmd = new Command("Ok");
final TextField txt = new TextField("Enter the text", null, 1024, 0);
frm.addCommand(cmd);
frm.append(txt);
frm.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c == cmd) {
return txt.getString(); // Error !!
} else {
return null; // Error !!
}
}
});
}
As you can see, I want to return the input dialog string, while the anonymous class method should return void. How can I resolve this problem?
This does not work as you expected.
I see there are already some solutions, but I feel a bit more discussion about what is actually going on might be helpful.
When you call the frm.setCommandListener(new CommandListener() { ... }) the code presents the user with a dialog where she can type in some text and submit, but the code does not stop and wait until the user finishes.
Instead the code continues to execute - without yielding the result. Only after the user finished typing and submits, you get called back to process the result - which might happen much later, or not at all.
I guess you have some code calling this method like:
public void someMethod(int foo, String bar) {
[...]
String result = MyInputForm.showInputDialog();
// do something with the result
System.out.println("hey, got a result "+ result);
[...]
}
Instead you need to reorganize this. First write a helper class handling the result:
public static class MyCallBack {
public MyCallBack(... /* here pass in what you need to process the result*/) {
... remember necessary stuff in instance variables
}
public void processResult(String result) {
// do something with the result
System.out.println("hey, got a result "+ result);
[...]
}
}
then the calling side does just:
public void someMethod(int foo, String bar) {
[...]
MyInputForm.showInputDialog( new MyCallBack(... here pass in stuff ...) );
[...]
}
and the actual code has to be changed to:
public static String showInputDialog(final MyCallBack callback) {
Form frm = new Form();
final Command cmd = new Command("Ok");
final TextField txt = new TextField("Enter the text", null, 1024, 0);
frm.addCommand(cmd);
frm.append(txt);
frm.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c == cmd) {
return callback.processResult(txt.getString());
} else {
return; // or just omit the else part
}
}
});
}
Two issues:
this way of programming feels pretty backwards, but it is really the way it works.
what feels not right is that I need to define a second helper class aside of the CommandListener. That is really not good style. I hope it can be improved, but as I do not see the complete code (which would be too much information anyway), I have to leave it to you to improve the code and get rid of the clutter. While I feel you want to have a modular, reusable input dialog helper, this might not be the best approach; better define the Form,TextField and Command directly where you need the result and get that running. Make it reusable in a second step after you get it running.
You don't need to return it if you instead do something with the String or store it somewhere, for example:
static String result;
public String commandAction(Command c, Displayable d) {
if (c == cmd) {
result = txt.getString();
} else {
result = null;
}
}
Although you'll have threading issues to deal with.
Given that CommandListener is fixed, 2 possible options are
Use a class member variable in the outer class & assign to that variable instead
private static String myText;
...
public static String showInputDialog() {
...
frm.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c == cmd) {
myText = txt.getString();
} else {
myText = null;
}
}
});
}
or Create a concrete implementation of your CommandListener and set the return value as a property of the new implementation
I would have a look at making the method/variable in this snippet non-static...
You cant return the string because you dont know when the listener will be called.
You can do something with it once you have the string though.
public static void showInputDialog() {
StringHandler sh = new StringHandler();
frm.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c == cmd) {
sh.handle(txt.getString());
} else {
sh.handle(null);
}
}
});}
public class StringHandler {
public void handle(String s){
// Do something with that string.
}
}

Categories