I have an unusual situation I am testing. I am using Espresso to write my tests. I know Espresso and InstrumentationTestCase is not meant to do this.
I have a Listener I created in one of my classes that will notify me of a change of a certain value. I use the listener in my test suite.
When I get the value from the listener, I need to assert the value was changed as such.
My problem is the test will end before I will receive the value form the listener.
private void sendSpeedChanges() {
setStaticSpeed(new Random().nextInt(10) + 2);
try {
runTestOnUiThread(new Runnable() {
#Override
public void run() {
consoleActivity.onSpeedChanged(getStaticSpeed(), false);
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
private void createSpeedDelegate() {
EspressoMachineValues.setOnSpeedChangeListener(new EspressoMachineValues.OnSpeedChangeListener() {
#Override
public void onSpeedChanged(double speed) {
//assert speed is correct.
assertTrue(getStaticSpeed() == speed);
}
});
}
These are the two methods I am using. The createSpeedDelegate() is call at the very beginning. Then I call sendSpeedChanges. I need to do this X-amount of times.
NOTE:
It takes about 200 milliseconds to retrieve info (On average).
I can't call sendSpeedChanges() until I have checked the value in onSpeedChange()
I cannot use Thread.sleep(); because the listener is on the main thread.
I have tried adding a getInstrumentation().wait(2000); and also getInstrumentation().waitForIdleSync(); Obviously, neither work.
In a perfect world, I would do this:
for (int i = 0; i < 42; i++) {
sendSpeedChanges();
i++;
}
But, this will not wait for the value to be checked. And if I do wait for the value, the test runner thinks all tests are done and terminates.
My question is, would there be a way to control when the test quits? Even though my tests appear to be done.
Alternatively, you could create an IdlingResource to monitor your speed. IdlingResource is the way Espresso uses to verify the Main Thread is idle or that there is no AsyncTasks running in the AsyncTask pool.
Have a loook at coutingIdlingResource class in the library source code. You could implement something similar to that. In your case, it could be something like this:
[...]
private int mTargetSpeed;
private volatile ResourceCallback resourceCallback;
#Override
public boolean isIdleNow() {
boolean isIdle = false;
if (getStaticSpeed() == mTargetSpeed) {
isIdle = true;
resourceCallback.onTransitionToIdle();
} else {
isIdle = false;
}
return isIdle;
}
On your tests, whenever you want to wait for the speed to reach the desired level, you should do:
[...]
SpeedIdlingResource speedIdlingResource = new SpeedIdlingResource ("my_idling_resource");
Espresso.registerIdlingResources(speedIdlingResource);
This way, Espresso will block until your idling resource tells the framework your SpeedMonitor is idle. That's goode because you leverage all Espresso synchronization framework to monitor when you reached the target speed, so your tests would be more reliable and faster than making a occupied wait.
In your test you will need to create a control statement that keeps that test running as long as you want it to be run.
while(myTestNeedsToRun) {
if(speedChangeReceived) {
sendSpeedChange();
speedChangeReceived = false;
}
}
private void createSpeedDelegate() {
EspressoMachineValues.setOnSpeedChangeListener(new EspressoMachineValues.OnSpeedChangeListener() {
#Override
public void onSpeedChanged(double speed) {
//assert speed is correct.
assertTrue(getStaticSpeed() == speed);
speedChangedReceived = true;
}
});
Once you decide you are finished running your test just set myTestNeedsToRun = false and then your test will end.
Related
I have a function
#Scheduled(fixedDelayString = "2000")
public void processPendingDownloadRequests() {
List<DownloadRequest> downloadRequests = downloadRequestService.getPendingDownloadRequests();
for (int i = 0; i < downloadRequests.size(); i++) {
DownloadRequest downloadRequest = downloadRequests.get(i);
processDownloadRequest(downloadRequest);
}
}
}
This will retrieve all download requests from the DB that are in the Pending state. Which is just a enum in the downloadrequest table.
#Async
public void processDownloadRequest(DownloadRequest downloadRequest) {
accountProfileProcessor.run(downloadRequest);
}
Inside the accountProfileProcessor is where the state of the downloadRequest changes to InProgress.
The race conditions comes when the #Scheduled function runs and picks up downloadRequests that have been submitted for Async jobs but the status hasn't been switched to inProgress yet. How can I avoid this?
I tried to only run the code inside the #Scheduled function if the #Async taskexecutor queue was empty but could not get it to work
The following will prevent two concurrent attempts to download the same resource.
Note that if there is a need to make sure that subsequent attempts to execute the same download are not repeated, some form of tracking that completion for a longer time is needed, with the need to somehow prevent memory leak (i.e. don't keep all complete id's in memory indefinitely).
private Set<String> activeDownloads = new HashSet<>();
#Async
public void processDownloadRequest(DownloadRequest downloadRequest) {
synchronized(this.activeDownloads) {
if (this.activeDownloads.contains(downloadRequest.getId()) {
// Duplicate download attempt - log it?
return;
} else {
this.activeDownloads.put(downloadRequest.getId());
}
}
try {
accountProfileProcessor.run(downloadRequest);
} finally {
synchronized(this.activeDownloads) {
this.activeDownloads.remove(downloadRequest.getId());
}
}
}
In a loop i need to make some checks, performed actually in some another verticle. In each iteration of my loop i need to check the response code, returned from those verticle and make some decision accordingly. In some other words i need to stop the execution of my loop and somehow wait till asynch. call returns. But such execution stop violates the vert.x philosophy, which states that main thread execution should be never stopped. How can i do it in the scope of Vert.x? So far i don't know how to do this. Any suggestions/code samples/urls to smth. like a solution would b highly appreciated.
Thanks!
When working with Vert.x you need to think less in terms of loops, and more in terms of callbacks.
You should use eventBus to communicate between vertices.
Let's say that what you want is something similar to this pseudocode:
for (int i = 0; i < 4; i++) {
int result = getVerticleResult();
System.out.println(result);
}
So, just a very basic example
class LooperVerticle extends AbstractVerticle {
private int i = 4;
#Override
public void start() throws Exception {
doWork();
}
private void doWork() {
vertx.eventBus().send("channel", "", (o) -> {
if (o.succeeded()) {
System.out.println(o.result().body());
i--;
if (i > 0) {
doWork();
}
}
});
}
}
class WorkerVerticle extends AbstractVerticle {
#Override
public void start() throws Exception {
vertx.eventBus().consumer("channel", (o) -> {
// Generate some random number
int num = ThreadLocalRandom.current().nextInt(0, 9);
// Simulate slowness
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
o.reply(num);
});
}
}
To test:
public class EventBusExample {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new LooperVerticle());
vertx.deployVerticle(new WorkerVerticle());
}
}
I think you need to use FutureTask and store them in a Collection and use FutureTask.get() to retrieve the result when needed which is a blocking call.
It sounds like a use case for reactive steam processing.
In general such problem could be solved using 2 parties:
a producer that executes tasks and returns asynchronous results
a handler that subscribes to results and performs another tasks
There is a way to configure producer to perform tasks only when there is a subscriber. And on other side subscriber can decide to unsubscribe from producer on some condition.
I'm not familiar with vertx capabilities for reactive streams. But I would start from RxJava integration
http://vertx.io/docs/vertx-rx/java/
Consider this code:
class Solver {
private boolean abort = false;
public void solve(List<Case> cases) {
while(!abort) {
for(Case c : cases)
compute(c); // method that take too long to finish
}
}
// a bunch of methods
public void abort() {
abort = true;
}
}
// in another class
Solver solver = new Solver();
solver.solve(cases);
public void onSolveAborted() {
solver.abort();
}
How can I change this solution so I can abort the solve function instantly. I know I can implements the Runnable interface in Solver class so I can stop the thread. This will introduce many changes in our code and I don't know if the framework we are using allow creating threads.
This will not be possible without the use of threads. Something has to set abort() before the running thread will stop. Take a look at this example:
class Solver implements Runnable {
private List<Case> cases;
public Solver(List<Case> cases) {
this.cases = cases;
}
private void compute(Case c) {
try {
// Do some computation here
} finally {
// Sound the horns! Abandon ship!
}
}
public void solve(List<Object> cases) {
for (Case c : cases) {
try {
compute(c); // method that take too long to finish
} catch (InterruptedException e) {
// Hmm, maybe I should take the hint...
break;
}
}
}
public void run() {
solve(cases);
}
public static void main(String args[]) {
List<Case> cases = new ArrayList<Case>();
// Populate cases
Thread t = new Thread(new Solver(cases));
t.run();
do {
// Wait 30 seconds
t.join(30 * 1000);
// Not done yet? Lets drop a hint..
if(t.isAlive()) {
t.interrupt();
}
} while (t.isAlive());
}
}
Very simply, it launches solve in a thread. The main thread waits up to 30 seconds then interrupts solve method. The solve method catches the interruption and gracefully exits the computation. Unlike your solution using boolean abort, this launches an InterruptedException from anywhere in your thead code (and you should deal with the exception accordingly!) allowing you to halt execution at any time.
If you want more control, you can add the try.. catch inside compute so you can have a finally clause to close any opened files or whatnot. Perhaps better still, have a try.. finally in compute to deal with closing things in a "nice" way and the try.. catch (InterruptedException) in the solve method to handle what happens in the case of interruption (in short, cleanup logic and interruption logic don't have to be in the same method).
Do somthing like this
Let say, you have 100 cases, 10 has been solved and you want to abort remaing 90.
In your code, you are solving all the cases in one iteration, after that while loop check for abort.
public void solve(List<Case> cases) {
Iterator<Case> iterator = cases.iterator();
while (iterator.hasNext() && !abort) {
Case c=iterator.iterator.next();
compute(c);
}
}
Change your class to Runnable and use ExecutorService to run it. Then you can just use methods "shutDown()" or "shutDownNow()" methods. This is cleaner and less intrusive then what you suggested in your own question. Plus killing thread manually is a REALLY BAD idea. At some point in JDK itself in thread method "kill()" was killed as there is no clean way to do so properly
I have to test that a Flash Player is correctly sending requests over the network. For that, I use BrowserMob Proxy to capture traffic.
My issue is I have to wait the end of the video played to test the final request. So as temp solution, in my test, I put a Thread.sleep(videoDuration). But IMO it's not really nice, and overall, the duration can change.
BrowserMob allow to add interceptor on the requests. So I think about notify and wait function.
Here my first try:
protected static boolean percent100Done;
protected static final Object percent100lock = new Object();
#BeforeClass
public static void addInterceptor() {
ProxyServer server = Server.init();
server.addRequestInterceptor((BrowserMobHttpRequest request, Har har) -> {
String percent = request.getProxyRequest().getParameter("percent");
if("100".equals(percent)) {
percent100Done = true;
synchronized (percent100lock) {
percent100lock.notify();
}
}
});
}
#Test
public void testFinalRequest() throws InterruptedException {
driver.get(myurl);
synchronized (percent100lock) {
while (!percent100Done) {
percent100lock.wait();
}
}
//test continue
}
I test this code, and it works. But it seems a bit dirty, especially the new Object line. What happen if I have to add notification for 25, 50 and 75 percents? I will have to 3 others booleans and lock?
Why not store the percentage and have a generic "progress" event, like how XMLHTTPRequest works?
protected static int percent;
protected static final Object progressLock = new Object();
#BeforeClass
public static void addInterceptor() {
ProxyServer server = Server.init();
server.addRequestInterceptor((BrowserMobHttpRequest request, Har har) -> {
synchronized(progressLock) {
percent = Integer.parseInt(request.getProxyRequest().getParameter("percent"));
progressLock.notify();
}
});
}
#Test
public void testFinalRequest() throws InterruptedException {
driver.get(myurl);
synchronized (progressLock) {
int lastPercent = -1;
while (percent != 100) {
if (lastPercent < 50 && percent >= 50) {
System.out.println("50%");
}
lastPercent = percent;
progressLock.wait();
}
}
//test continue
}
In terms of weirdness, I think your solution is fine. It looks strange, but every Object has a lock, so you might as well use it. If you needed to do something more complicated, you might want to look at Lock and it's subclasses. For example, with a ReadWriteLock, multiple readers can hold the lock at the same time, but only one writer can. It doesn't look like you have multiple readers though (and I wouldn't expect locking to effect the performance of this program much).
I have a class proposing translations utilities. The translations themselves should be reloaded every 30 minutes. I use Spring Timer support for that. Basically, my class looks like :
public interface Translator {
public void loadTranslations();
public String getTranslation(String key);
}
loadTranslations() can be pretty long to run, so while it is running the old translations are still available. This is done by loading the translations in a local Map and just changing the reference when all translations are loaded.
My problem is : how do I make sure that when a thread is already loading translations, is a second one also tries to run, it detects that and returns immediately, without starting a second update.
A synchronized method will only queue the loads ... I'm still on Java 1.4, so no java.util.concurrent.
Thanks for your help !
Use some form of locking mechanism to only perform the task if it is not already in progress. Acquiring the locking token must be a one-step process. See:
/**
* #author McDowell
*/
public abstract class NonconcurrentTask implements Runnable {
private boolean token = true;
private synchronized boolean acquire() {
boolean ret = token;
token = false;
return ret;
}
private synchronized void release() {
token = true;
}
public final void run() {
if (acquire()) {
try {
doTask();
} finally {
release();
}
}
}
protected abstract void doTask();
}
Test code that will throw an exception if the task runs concurrently:
public class Test {
public static void main(String[] args) {
final NonconcurrentTask shared = new NonconcurrentTask() {
private boolean working = false;
protected void doTask() {
System.out.println("Working: "
+ Thread.currentThread().getName());
if (working) {
throw new IllegalStateException();
}
working = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!working) {
throw new IllegalStateException();
}
working = false;
}
};
Runnable taskWrapper = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
shared.run();
}
}
};
for (int i = 0; i < 100; i++) {
new Thread(taskWrapper).start();
}
}
}
I am from a .net background(no java experience at all), but you could try a simple static flag of some sort that checks at the beginning of the method if its alrady running. Then all you need to do is make sure any read/write of that flag is synchronized. So at beginning check the flag, if its not set, set it, if it is set, return. If its not set, run the rest of the method, and after its complete, unset it. Just make sure to put the code in a try/finally and the flag iunsetting in the finally so it always gets unset in case of error. Very simplified but may be all you need.
Edit: This actually probably works better than synchronizing the method. Because do you really need a new translation immediately after the one before it finishes? And you may not want to lock up a thread for too long if it has to wait a while.
Keep a handle on the load thread to see if it's running?
Or can't you just use a synchronized flag to indicate if a load is in progress?
This is actually identical to the code that is required to manage the construction of a Singleton (gasp!) when done the classical way:
if (instance == null) {
synchronized {
if (instance == null) {
instance = new SomeClass();
}
}
}
The inner test is identical to the outer test. The outer test is so that we dont routinely enter a synchronised block, the inner test is to confirm that the situation has not changed since we last made the test (the thread could have been preempted before entering Synchronized).
In your case:
if (translationsNeedLoading()) {
synchronized {
if (translationsNeedLoading()) {
loadTranslations();
}
}
}
UPDATE: This way of constructing a singleton will not work reliably under your JDK1.4. For explanation see here. However I think you are you will be OK in this scenario.