How to make runBlocking wait for "all threads" in Unit Testing? - mockito

I'm trying to write a unit test for getUser() function:
fun getUser(userId:Int) {
// some code...
launchDataOperation { api.getUser(userId) }
}
The issue I can see (but don't know how to resolve in a clean way) is launchDataOperation(...) creates a coroutine to call suspend function api.getUser:
fun launchDataOperation(block: suspend () -> Unit): Job {
return coroutineScope.launch {
try {
setLoading(true)
block()
} catch (error: NetworkConnectionException) {
setError(Errors.NETWORK_CONNECTION_ERROR)
} catch (error: DataOperationException) {
setMessage(error.getErrors())
} finally {
setLoading(false)
}
}
}
This is my failing test:
#Test
fun `error message is displayed if api error occurred`() {
val exception = DataOperationException(listOf("FATAL ERROR"))
runBlocking {
`when`(api.getUser(anyInt())).thenAnswer { throw exception }
subject.getUser(userId)
// execution fails if the below line is commented
// this is not the correct way to wait for other coroutines
delay(500) // wait for 500ms till the other coroutines finish
assertThat(subject.messages.value).isEqualTo(exception.getErrors())
}
}

Related

CompletableFuture executing at server startup and not when invoked

I have two CompletableFutures and one combining them as below and they are getting executed on server start up and not when I call them. How do I make them execute when I call them?
#Service
public class testFutures {
public String runFutures(){
return combinedFuture;
}
CompletableFuture<String> future1(){
return CompletableFuture.supplyAsync(() -> {
System.out.println("Future 1");
return "Future 1"
});
}
CompletableFuture<String> future2(){
return CompletableFuture.supplyAsync(() -> {
System.out.println("Future 2");
return "Future 2";
});
}
CompletableFuture<String> combinedFuture = future1().thenCombine(future2(),
(future1, future2) -> {
System.out.println("Combined Future);
return "Combined Future";
});
}

Get return value from thread, is this Kotlin code thread safe?

I would like to run some treads, wait till all of them are finished and get the results.
Possible way to do that would be in the code below. Is it thread safe though?
import kotlin.concurrent.thread
sealed class Errorneous<R>
data class Success<R>(val result: R) : Errorneous<R>()
data class Fail<R>(val error: Exception) : Errorneous<R>()
fun <R> thread_with_result(fn: () -> R): (() -> Errorneous<R>) {
var r: Errorneous<R>? = null
val t = thread {
r = try { Success(fn()) } catch (e: Exception) { Fail(e) }
}
return {
t.join()
r!!
}
}
fun main() {
val tasks = listOf({ 2 * 2 }, { 3 * 3 })
val results = tasks
.map{ thread_with_result(it) }
.map{ it() }
println(results)
}
P.S.
Are there better built-in tools in Kotlin to do that? Like process 10000 tasks with pool of 10 threads?
It should be threads, not coroutines, as it will be used with legacy code and I don't know if it works well with coroutines.
Seems like Java has Executors that doing exactly that
fun <R> execute_in_parallel(tasks: List<() -> R>, threads: Int): List<Errorneous<R>> {
val executor = Executors.newFixedThreadPool(threads)
val fresults = executor.invokeAll(tasks.map { task ->
Callable<Errorneous<R>> {
try { Success(task()) } catch (e: Exception) { Fail(e) }
}
})
return fresults.map { future -> future.get() }
}

Limit concurrent method executions inside call()

I have a call() method in my code, which based on certain conditions calls specific methods :
call(){
if(a){
methodA();
}
if(b){
methodB();
}
if(c){
methodC();
}
}
In the above scenario, I want to limit concurrent executions for methodC.
How can this be achieved?
What you need here is a Semaphore construct (check the bouncer/night club specification in the example).
// Create the semaphore with 3 slots, where 3 are available.
var bouncer = new Semaphore(3, 3);
call(){
if(a){
methodA();
}
if(b){
methodB();
}
if(c){
// Let a thread execute only after acquiring access (a semaphore to be released).
Bouncer.WaitOne();
methodC();
// This thread is done. Let someone else go for it
Bouncer.Release(1);
}
}
If you want to limit the number of concurrent executions to at most one at a time, then you should use a Lock. In Java it should look like:
final Lock lock = new ReentrantLock();
call() {
if(a) {
methodA();
}
if(b) {
methodB();
}
if(c) {
lock.lock();
try {
methodC();
} finally {
lock.unlock();
}
}
}
If you want to limit the number of concurrent executions to more than one at a time, you can use a Semaphore; here CONCURRENT_CALLS_ALLOWED is an int.
final Semaphore semaphore = new Semaphore(CONCURRENT_CALLS_ALLOWED);
call() {
if(a) {
methodA();
}
if(b) {
methodB();
}
if(c) {
semaphore.aquire();//throws checked exception
try {
methodC();
} finally {
semaphore.release();
}
}
}

Making an asynchronous function synchronous for the Node.js REPL

I have a library that connects to a remote API:
class Client(access_token) {
void put(key, value, callback);
void get(key, callback);
}
I want to set up a Node.js REPL to make it easy to try things out:
var repl = require('repl');
var r = repl.start('> ');
r.context.client = new Client(...);
The problem is that an asynchronous API is not convenient for a REPL. I'd prefer a synchronous one that yields the result via the return value and signals an error with an exception. Something like:
class ReplClient(access_token) {
void put(key, value); // throws NetworkError
string get(key); // throws NetworkError
}
Is there a way to implement ReplClient using Client? I'd prefer to avoid any dependencies other than the standard Node.js packages.
You can synchronously wait for stuff with the magic of wait-for-stuff.
Based on your example specification:
const wait = require('wait-for-stuff')
class ReplClient {
constructor(access_token) {
this.client = new Client(access_token)
}
put(key, value) {
return checkErr(wait.for.promise(this.client.put(key, value)))
}
get(key) {
return checkErr(wait.for.promise(this.client.get(key)))
}
}
const checkErr = (maybeErr) => {
if (maybeErr instanceof Error) {
throw maybeErr
} else {
return maybeErr
}
}

Construct Task from WaitHandle.Wait

I chose to return Task<T> and Task from my objects methods to provide easy consumation by the gui. Some of the methods simply wait for mutex of other kind of waithandles . Is there a way to construct Task from WaitHandle.Wait() so that I don't have to block one treadpool thread for that.
There is a way to do this: you can subscribe to WaitHandle using ThreadPool.RegisterWaitForSingleObject method and wrap it via TaskCompletionSource class:
public static class WaitHandleEx
{
public static Task ToTask(this WaitHandle waitHandle)
{
var tcs = new TaskCompletionSource<object>();
// Registering callback to wait till WaitHandle changes its state
ThreadPool.RegisterWaitForSingleObject(
waitObject: waitHandle,
callBack:(o, timeout) => { tcs.SetResult(null); },
state: null,
timeout: TimeSpan.MaxValue,
executeOnlyOnce: true);
return tcs.Task;
}
}
Usage:
WaitHandle wh = new AutoResetEvent(true);
var task = wh.ToTask();
task.Wait();
As noted by #gordy in the comments of the accepted answer of Sergey Teplyakov, MSDN proposes an implementation with unsubscription of the registered WaitHandle.
I slightly modified it here to support the result of the callback: if the registration has timed out, the task return false. If the signal has been received, the task return true:
public static class ExtensionMethods
{
public static Task<bool> WaitOneAsync(this WaitHandle waitHandle, int timeoutMs)
{
if (waitHandle == null)
throw new ArgumentNullException(nameof(waitHandle));
var tcs = new TaskCompletionSource<bool>();
RegisteredWaitHandle registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(
waitHandle,
callBack: (state, timedOut) => { tcs.TrySetResult(!timedOut); },
state: null,
millisecondsTimeOutInterval: timeoutMs,
executeOnlyOnce: true);
return tcs.Task.ContinueWith((antecedent) =>
{
registeredWaitHandle.Unregister(waitObject: null);
try
{
return antecedent.Result;
}
catch
{
return false;
}
});
}
}
Usage is same as the original answer:
WaitHandle signal = new AutoResetEvent(initialState: false);
bool signaled = await signal.WaitOneAsync(1000);
if (signaled)
{
Console.WriteLine("Signal received");
}
else
{
Console.WriteLine("Waiting signal timed out");
}

Resources