Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup refactor #233

Merged
merged 7 commits into from
Aug 16, 2017
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import com.wix.detox.systeminfo.Environment;
import com.wix.invoke.MethodInvocation;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
Expand Down Expand Up @@ -119,7 +122,16 @@ public void run() {
break;
case "cleanup":
wsClient.sendAction("cleanupDone", Collections.emptyMap(), messageId);
stop();
try {
boolean stopRunner = new JSONObject(params).getBoolean("stopRunner");
if (stopRunner) {
stop();
} else {
ReactNativeSupport.removeEspressoIdlingResources(reactNativeHostHolder);
}
} catch (JSONException e) {
Log.e(LOG_TAG, "cleanup cmd doesn't have stopRunner param");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@simonracz I'm working on refactoring this switch/case clause (almost done), and couldn't help but wonder whether there was a particular reason no to fallback to a stopRunner=false behavior in case stopRunner was not provided. It's easy to do so using optBoolean("stopRunner", false) (instead of getBoolean()). I'd appreciate your input :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... or should it actually be a fallback to true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @d4vidi ,

The short answer is, I don't remember. :)

In general treat my code as POC. So, feel free to refactor it and double check my decisions.

For this specific case, I think it would be safe to go with optBoolean here.

Cheers,
Simon

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds about right :) so what's left now is to decided whether the default should be true or false :)

}
break;
case "reactNativeReload":
UiAutomatorHelper.espressoSync();
Expand All @@ -138,6 +150,6 @@ public void onConnect() {

@Override
public void onClosed() {
// stop();
stop();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ private static void setupEspressoIdlingResources(
rnUIModuleIdlingResource);
}

private static ArrayList<IdlingResource> looperIdlingResources = new ArrayList<>();
private static ArrayList<LooperIdlingResource> looperIdlingResources = new ArrayList<>();

private static void setupReactNativeQueueInterrogators(@NonNull Object reactContext) {
HashSet<Looper> excludedLoopers = new HashSet<>();
Expand Down Expand Up @@ -364,7 +364,8 @@ private static void removeEspressoIdlingResources(
}

private static void removeReactNativeQueueInterrogators() {
for (IdlingResource res : looperIdlingResources) {
for (LooperIdlingResource res : looperIdlingResources) {
res.stop();
Espresso.unregisterIdlingResources(res);
}
looperIdlingResources.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,27 @@ public void onPong(Buffer payload) {
// empty
}

private volatile boolean closing = false;

@Override
public void onClose(int code, String reason) {
Log.i(LOG_TAG, "At onClose");
Log.d(LOG_TAG, "Detox Closed: " + code + " " + reason);
closing = true;
actionHandler.onClosed();
}

public void close() {
if (closing) {
return;
}
closing = true;
try {
websocket.close(NORMAL_CLOSURE_STATUS, null);
} catch (IOException e) {
Log.e(LOG_TAG, "WS close", e);
Log.i(LOG_TAG, "WS close", e);
} catch (IllegalStateException e) {
Log.i(LOG_TAG, "WS close", e);
}
}

Expand All @@ -102,9 +111,6 @@ public void close() {

private static final int NORMAL_CLOSURE_STATUS = 1000;

// TODO
// Need an API to stop the websocket from DetoxManager

public WebSocketClient(ActionHandler actionHandler) {
this.actionHandler = actionHandler;
}
Expand Down Expand Up @@ -167,8 +173,7 @@ public void receiveAction(WebSocket webSocket, String json) {
long messageId = object.getLong("messageId");

Log.d(LOG_TAG, "Detox Action Received: " + type);
// TODO
// This is just a dummy call now. Finish parsing params.

if (actionHandler != null) actionHandler.onAction(type, params.toString(), messageId);
} catch (JSONException e) {
Log.e(LOG_TAG, "Detox Error: receiveAction decode - " + e.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ public float[] calculateCoordinates(View view) {
Tap.SINGLE, c, Press.FINGER, InputDevice.SOURCE_UNKNOWN, MotionEvent.BUTTON_PRIMARY));
}

private final static int DEFAULT_SCROLL_DP = 500;

/**
* Scrolls to the edge of the given scrollable view.
*
Expand Down Expand Up @@ -92,39 +90,31 @@ public void perform(UiController uiController, View view) {
if (view instanceof AbsListView) {
RNScrollListener l = new RNScrollListener((AbsListView) view);
do {
ScrollHelper.perform(uiController, view, edge, DEFAULT_SCROLL_DP);
ScrollHelper.performOnce(uiController, view, edge);
} while (l.didScroll());
l.cleanup();
uiController.loopMainThreadUntilIdle();
return;
} if (view instanceof ScrollView) {
} else if (view instanceof ScrollView) {
int prevScrollY = view.getScrollY();
while (true) {
ScrollHelper.perform(uiController, view, edge, DEFAULT_SCROLL_DP);
ScrollHelper.performOnce(uiController, view, edge);
int currentScrollY = view.getScrollY();
if (currentScrollY == prevScrollY) break;
prevScrollY = currentScrollY;
}
uiController.loopMainThreadUntilIdle();
return;
} if (view instanceof HorizontalScrollView) {
} else if (view instanceof HorizontalScrollView) {
int prevScrollX = view.getScrollX();
while (true) {
ScrollHelper.perform(uiController, view, edge, DEFAULT_SCROLL_DP);
ScrollHelper.performOnce(uiController, view, edge);
int currentScrollX = view.getScrollX();
if (currentScrollX == prevScrollX) break;
prevScrollX = currentScrollX;
}
uiController.loopMainThreadUntilIdle();
return;
} else if (recyclerViewClass != null && recyclerViewClass.isInstance(view)) {
RecyclerViewScrollListener l = new RecyclerViewScrollListener(view);
do {
ScrollHelper.perform(uiController, view, edge, DEFAULT_SCROLL_DP);
ScrollHelper.performOnce(uiController, view, edge);
} while (l.didScroll());
l.cleanup();
uiController.loopMainThreadUntilIdle();
return;
} else {
throw new RuntimeException(
"Only descendants of AbsListView, ScrollView, HorizontalScrollView and RecyclerView are supported");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,23 @@ final public class LooperIdlingResource implements IdlingResource {

private ResourceCallback resourceCallback;

private ResourceCallbackIdleHandler resIdleHandler = null;

public LooperIdlingResource(Looper monitoredLooper, boolean considerWaitIdle) {
this.monitoredLooper = monitoredLooper;
this.monitoredHandler = new Handler(monitoredLooper);
this.considerWaitIdle = considerWaitIdle;
}

/**
* Call this to properly stop the LooperIR.
*/
public void stop() {
if (resIdleHandler != null) {
resIdleHandler.stop = true;
}
}

// Only assigned and read from the main loop.
private QueueInterrogator queueInterrogator;

Expand All @@ -51,8 +62,11 @@ public boolean isIdleNow() {
resourceCallback.onTransitionToIdle();
}
}
Log.i(LOG_TAG, getName() + " looper is idle : " + String.valueOf(idle || idleWait));
return idle || idleWait;
idle = idle || idleWait;
if (!idle) {
Log.i(LOG_TAG, getName() + " looper is busy");
}
return idle;
}

@Override
Expand All @@ -62,16 +76,17 @@ public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
queueInterrogator = new QueueInterrogator(monitoredLooper);

// must load idle handlers from monitored looper thread.
IdleHandler idleHandler = new ResourceCallbackIdleHandler(resourceCallback, queueInterrogator,
resIdleHandler = new ResourceCallbackIdleHandler(resourceCallback, queueInterrogator,
monitoredHandler);

monitoredHandler.postAtFrontOfQueue(new Initializer(idleHandler));
monitoredHandler.postAtFrontOfQueue(new Initializer(resIdleHandler));
}

private static class ResourceCallbackIdleHandler implements IdleHandler {
private final ResourceCallback resourceCallback;
private final QueueInterrogator myInterrogator;
private final Handler myHandler;
public volatile boolean stop = false;

ResourceCallbackIdleHandler(ResourceCallback resourceCallback,
QueueInterrogator myInterrogator, Handler myHandler) {
Expand All @@ -93,7 +108,7 @@ public boolean queueIdle() {
myHandler.sendEmptyMessage(-1);
}

return true;
return !stop;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ public String getName() {
@Override
public boolean isIdleNow() {
boolean ret = idleNow.get();
Log.i(LOG_TAG, "JS Bridge is idle : " + String.valueOf(ret));
if (!ret) {
Log.i(LOG_TAG, "JS Bridge is busy");
}
return ret;
}

Expand All @@ -44,12 +46,12 @@ public void onTransitionToBridgeIdle() {
if (callback != null) {
callback.onTransitionToIdle();
}
Log.i(LOG_TAG, "JS Bridge transitions to idle.");
// Log.i(LOG_TAG, "JS Bridge transitions to idle.");
}

//Proxy calls it
public void onTransitionToBridgeBusy() {
idleNow.set(false);
Log.i(LOG_TAG, "JS Bridge transitions to busy.");
// Log.i(LOG_TAG, "JS Bridge transitions to busy.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ public boolean isIdleNow() {
if (callback != null) {
callback.onTransitionToIdle();
}
Log.i(LOG_TAG, "JS Timer is idle: true");
// Log.i(LOG_TAG, "JS Timer is idle: true");
return true;
}
}

Choreographer.getInstance().postFrameCallback(this);
Log.i(LOG_TAG, "JS Timer is idle: false");
Log.i(LOG_TAG, "JS Timer is busy");
return false;
} catch (ReflectException e) {
Log.e(LOG_TAG, "Can't set up RN timer listener", e.getCause());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public boolean isIdleNow() {
if (callback != null) {
callback.onTransitionToIdle();
}
Log.i(LOG_TAG, "UIManagerModule is idle.");
// Log.i(LOG_TAG, "UIManagerModule is idle.");
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,44 @@ private static float[][] interpolate(float[] start, float[] end, int steps) {

return res;
}

/**
* Scrolls the View in a direction once by the maximum amount possible. (Till the edge
* of the screen.)
*
* Direction
* 1 -> left
* 2 -> Right
* 3 -> Up
* 4 -> Down
*
* @param direction Direction to scroll
*/
public static void performOnce(UiController uiController, View view, int direction) {
int adjWidth = 0;
int adjHeight = 0;

int[] pos = new int[2];
view.getLocationInWindow(pos);

float[] screenSize = UiAutomatorHelper.getScreenSizeInPX();

if (direction == 1) {
adjWidth = (int) ((screenSize[0] - pos[0]) * (1 - 2 * DEFAULT_DEADZONE_PERCENT));
} else if (direction == 2) {
adjWidth = (int) ((pos[0] + view.getWidth()) * (1 - 2 * DEFAULT_DEADZONE_PERCENT));
} else if (direction == 3) {
adjHeight = (int) ((screenSize[1] - pos[1]) * (1 - 2 * DEFAULT_DEADZONE_PERCENT));
} else {
adjHeight = (int) ((pos[1] + view.getHeight()) * (1 - 2 * DEFAULT_DEADZONE_PERCENT));
}

if (direction == 1 || direction == 2) {
doScroll(uiController, view, direction, adjWidth);
} else {
doScroll(uiController, view, direction, adjHeight);
}

uiController.loopMainThreadUntilIdle();
}
}
2 changes: 1 addition & 1 deletion detox/src/Detox.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class Detox {

async beforeEach(...testNameComponents) {
this._currentTestNumber++;
if(this._artifactsPathsProvider !== undefined) {
if (this._artifactsPathsProvider !== undefined) {
const testArtifactsPath = this._artifactsPathsProvider.createPathForTest(this._currentTestNumber, ...testNameComponents)
this.device.setArtifactsDestination(testArtifactsPath);
}
Expand Down
12 changes: 9 additions & 3 deletions detox/src/client/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class Client {
this.ws = new AsyncWebSocket(config.server);
this.slowInvocationStatusHandler = null;
this.slowInvocationTimeout = argparse.getArgValue('debug-synchronization');
this.successfulTestRun = true; // flag for cleanup
}

async connect() {
Expand All @@ -29,7 +30,7 @@ class Client {

async cleanup() {
if (this.ws.isOpen()) {
await this.sendAction(new actions.Cleanup());
await this.sendAction(new actions.Cleanup(this.successfulTestRun));
}
}

Expand All @@ -49,7 +50,12 @@ class Client {
if (this.slowInvocationTimeout) {
this.slowInvocationStatusHandler = this.slowInvocationStatus();
}
await this.sendAction(new actions.Invoke(invocation));
try {
await this.sendAction(new actions.Invoke(invocation));
} catch (err) {
this.successfulTestRun = false;
throw new Error(err);
}
clearTimeout(this.slowInvocationStatusHandler);
}

Expand All @@ -61,7 +67,7 @@ class Client {
}

slowInvocationStatus() {
return setTimeout( async () => {
return setTimeout(async () => {
const status = await this.currentStatus();
this.slowInvocationStatusHandler = this.slowInvocationStatus();
}, this.slowInvocationTimeout);
Expand Down
Loading