Mailbox is a ForkJoinTask but the ExecutorService can be a ThreadPoolExecutor: is this fine? - concurrency

In Akka 2.6.10, the Mailbox is a ForkJoinTask as well as a Runnable.
private[akka] abstract class Mailbox(val messageQueue: MessageQueue)
extends ForkJoinTask[Unit]
with SystemMessageQueue
with Runnable {
// Runnable method
override final def run(): Unit = {
// ...
processMailbox()
dispatcher.registerForExecution(this, false, false)
// ...
}
// ForkJoinTask method
final override def exec(): Boolean = {
// ...
run()
// ...
}
}
But the executor service can be configured to use TheadPoolExecutor (TP) rather than ForkJoinPool (FJ). Therefore it is possible that a TP executes a ForkJoinTask.
This maybe totally reasonable but the fact that a TP executes an FJ task looks a bit weird to me. Can anyone share the decision reasoning here? How does ForkJoinTask benefit Akka even if it can be executed by a TheadPoolExecutor?

Related

Missing capabilities for unit test

I've implemented a C++ Class that will execute something in a timed cycle using a thread. The thread is set to be scheduled with the SCHED_DEADLINE scheduler of the Linux kernel. To setup the Scheduler the process running this must have certain Linux capabilities.
My question is, how to test this?
I can of course make a unit test and create the threat, do some counting an exit the test after a time to validate the cycle counter but that only works if the unit test is allowed to apply the right scheduler. If not, the default scheduler applies and the timing of the cyclic loops will be immediate and therefore executes a different behaviour.
How would you test this scenario?
Some Code Example:
void thread_handler() {
// setup SCHED_DEADLINE Parameters
while (running) {
// execute application logic
sched_yield();
}
}
There two separate units to test here. First the cyclic execution of code and second the strategy with the os interface. The first unit would look like this:
class CyclicThread : public std::thread {
public:
CyclicThread(Strategy& strategy) :
std::thread(bind(&CyclicThread::worker, this)),
strategy(strategy) { }
add_task(std::function<void()> handler) {
...
}
private:
Strategy& strategy;
void worker() {
while (running) {
execute_handler()
strategy.yield();
}
}
}
This is fairly easy to test with a mock object of the strategy.
The Deadline scheduling strategy looks like this:
class DeadlineStrategy {
public:
void yield() {
sched_yield();
}
}
This class can also be tested fairly easy by mocking the sched_yield() system call.

Kotlin runTest with delay() is not working

I am testing a coroutine that blocks. Here is my production code:
interface Incrementer {
fun inc()
}
class MyViewModel : Incrementer, CoroutineScope {
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO
private val _number = MutableStateFlow(0)
fun getNumber(): StateFlow<Int> = _number.asStateFlow()
override fun inc() {
launch(coroutineContext) {
delay(100)
_number.tryEmit(1)
}
}
}
And my test:
class IncTest {
#BeforeEach
fun setup() {
Dispatchers.setMain(StandardTestDispatcher())
}
#AfterEach
fun teardown() {
Dispatchers.resetMain()
}
#Test
fun incrementOnce() = runTest {
val viewModel = MyViewModel()
val results = mutableListOf<Int>()
val resultJob = viewModel.getNumber()
.onEach(results::add)
.launchIn(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
launch(StandardTestDispatcher(testScheduler)) {
viewModel.inc()
}.join()
assertEquals(listOf(0, 1), results)
resultJob.cancel()
}
}
How would I go about testing my inc() function? (The interface is carved in stone, so I can't turn inc() into a suspend function.)
There are two problems here:
You want to wait for the work done in the coroutine that viewModel.inc() launches internally.
Ideally, the 100ms delay should be fast-forwarded during tests so that it doesn't actually take 100ms to execute.
Let's start with problem #2 first: for this, you need to be able to modify MyViewModel (but not inc), and change the class so that instead of using a hardcoded Dispatchers.IO, it receives a CoroutineContext as a parameter. With this, you could pass in a TestDispatcher in tests, which would use virtual time to fast-forward the delay. You can see this pattern described in the Injecting TestDispatchers section of the Android docs.
class MyViewModel(coroutineContext: CoroutineContext) : Incrementer {
private val scope = CoroutineScope(coroutineContext)
private val _number = MutableStateFlow(0)
fun getNumber(): StateFlow<Int> = _number.asStateFlow()
override fun inc() {
scope.launch {
delay(100)
_number.tryEmit(1)
}
}
}
Here, I've also done some minor cleanup:
Made MyViewModel contain a CoroutineScope instead of implementing the interface, which is an officially recommended practice
Removed the coroutineContext parameter passed to launch, as it doesn't do anything in this case - the same context is in the scope anyway, so it'll already be used
For problem #1, waiting for work to complete, you have a few options:
If you've passed in a TestDispatcher, you can manually advance the coroutine created inside inc using testing methods like advanceUntilIdle. This is not ideal, because you're relying on implementation details a lot, and it's something you couldn't do in production. But it'll work if you can't use the nicer solution below.
viewModel.inc()
advanceUntilIdle() // Returns when all pending coroutines are done
The proper solution would be for inc to let its callers know when it's done performing its work. You could make it a suspending method instead of launching a new coroutine internally, but you stated that you can't modify the method to make it suspending. An alternative - if you're able to make this change - would be to create the new coroutine in inc using the async builder, returning the Deferred object that that creates, and then await()-ing at the call site.
override fun inc(): Deferred<Unit> {
scope.async {
delay(100)
_number.tryEmit(1)
}
}
// In the test...
viewModel.inc().await()
If you're not able to modify either the method or the class, there's no way to avoid the delay() call causing a real 100ms delay. In this case, you can force your test to wait for that amount of time before proceeding. A regular delay() within runTest would be fast-forwarded thanks to it using a TestDispatcher for the coroutine it creates, but you can get away with one of these solutions:
// delay() on a different dispatcher
viewModel.inc()
withContext(Dispatchers.Default) { delay(100) }
// Use blocking sleep
viewModel.inc()
Thread.sleep(100)
For some final notes about the test code:
Since you're doing Dispatchers.setMain, you don't need to pass in testScheduler into the TestDispatchers you create. They'll grab the scheduler from Main automatically if they find a TestDispatcher there, as described in its docs.
Instead of creating a new scope to pass in to launchIn, you could simply pass in this, the receiver of runTest, which points to a TestScope.

How to unit test Kotlin suspending functions

I follow the MVP pattern + UseCases to interact with a Model layer. This is a method in a Presenter I want to test:
fun loadPreviews() {
launch(UI) {
val items = previewsUseCase.getPreviews() // a suspending function
println("[method] UseCase items: $items")
println("[method] View call")
view.showPreviews(items)
}
}
My simple BDD test:
fun <T> givenSuspended(block: suspend () -> T) = BDDMockito.given(runBlocking { block() })
infix fun <T> BDDMockito.BDDMyOngoingStubbing<T>.willReturn(block: () -> T) = willReturn(block())
#Test
fun `load previews`() {
// UseCase and View are mocked in a `setUp` method
val items = listOf<PreviewItem>()
givenSuspended { previewsUseCase.getPreviews() } willReturn { items }
println("[test] before Presenter call")
runBlocking { presenter.loadPreviews() }
println("[test] after Presenter call")
println("[test] verify the View")
verify(view).showPreviews(items)
}
The test passes successfully but there's something weird in the log. I expect it to be:
"[test] before Presenter call"
"[method] UseCase items: []"
"[method] View call"
"[test] after Presenter call"
"[test] verify the View"
But it turns out to be:
[test] before Presenter call
[test] after Presenter call
[test] verify the View
[method] UseCase items: []
[method] View call
What's the reason of this behaviour and how should I fix it?
I've found out that it's because of a CoroutineDispatcher. I used to mock UI context with EmptyCoroutineContext. Switching to Unconfined has solved the problem
Update 02.04.20
The name of the question suggests that there'll be an exhaustive explanation how to unit test a suspending function. So let me explain a bit more.
The main problem with testing a suspending function is threading. Let's say we want to test this simple function that updates a property's value in a different thread:
class ItemUpdater(val item: Item) {
fun updateItemValue() {
launch(Dispatchers.Default) { item.value = 42 }
}
}
We need to somehow replace Dispatchers.Default with an another dispatcher only for testing purposes. There're two ways how we can do that. Each has its pros and cons, and which one to choose depends on your project & style of coding:
1. Inject a Dispatcher.
class ItemUpdater(
val item: Item,
val dispatcher: CoroutineDispatcher // can be a wrapper that provides multiple dispatchers but let's keep it simple
) {
fun updateItemValue() {
launch(dispatcher) { item.value = 42 }
}
}
// later in a test class
#Test
fun `item value is updated`() = runBlocking {
val item = Item()
val testDispatcher = Dispatchers.Unconfined // can be a TestCoroutineDispatcher but we still keep it simple
val updater = ItemUpdater(item, testDispatcher)
updater.updateItemValue()
assertEquals(42, item.value)
}
2. Substitute a Dispatcher.
class ItemUpdater(val item: Item) {
fun updateItemValue() {
launch(DispatchersProvider.Default) { item.value = 42 } // DispatchersProvider is our own global wrapper
}
}
// later in a test class
// -----------------------------------------------------------------------------------
// --- This block can be extracted into a JUnit Rule and replaced by a single line ---
// -----------------------------------------------------------------------------------
#Before
fun setUp() {
DispatchersProvider.Default = Dispatchers.Unconfined
}
#After
fun cleanUp() {
DispatchersProvider.Default = Dispatchers.Default
}
// -----------------------------------------------------------------------------------
#Test
fun `item value is updated`() = runBlocking {
val item = Item()
val updater = ItemUpdater(item)
updater.updateItemValue()
assertEquals(42, item.value)
}
Both of them are doing the same thing - they replace the original Dispatchers.Default in test classes. The only difference is how they do that. It's really really up to you which of them to choose so don't get biased by my own thoughts below.
IMHO: The first approach is a little too much cumbersome. Injecting dispatchers everywhere will result into polluting most of the classes' constructors with an extra DispatchersWrapper only for a testing purpose. However Google recommends this way at least for now. The second style keeps things simple and it doesn't complicate the production classes. It's like an RxJava's way of testing where you have to substitute schedulers via RxJavaPlugins. By the way, kotlinx-coroutines-test will bring the exact same functionality someday in future.
I see you found out on you own, but I'd like to explain a bit more for the people that might run into the same problem
When you do launch(UI) {}, a new coroutine is created and dispatched to the "UI" Dispatcher, that means that your coroutine now runs on a different thread.
Your runBlocking{} call create a new coroutine, but runBlocking{} will wait for this coroutine to end before continuing, your loadPreviews() function creates a coroutine, start it and then return immediately, so runBlocking() just wait for it and return.
So while runBlocking{} has returned, the coroutine that you created with launch(UI){} is still running in a different thread, that's why the order of your log is messed up
The Unconfined context is a special CoroutineContext that simply create a dispatcher that execute the coroutine right there on the current thread, so now when you execute runBlocking{}, it has to wait for the coroutine created by launch{} to end because it is running on the same thread thus blocking that thread.
I hope my explanation was clear, have a good day

Subactor (worker) still works after Main actor Timeout in Java Akka

I have implemented an application in Akka framework using Java. I have a main actor which calls sub-actor by using 'Ask' method and timeout after 60 seconds, the worker calls another java class method once it receives the message from Main Actor.
Now the problem is though my Main actor timed-out after 60 seconds still the worker is able to talk to the java class method and in-turn the method is performing the operations which is not required as the main actor cannot receive the response though the sub-actor returns that due to the timeout.
Is there anyway I can kill the worker or stop it from further processing if my Main actor timeout?
I checked the methods like RecieveTimeOut(), context.stop() and poisonpill but still no use.
Appreciate your support
Code Below
public class MainActor extends UntypedActor {
ActorRef subActorRef;
final Timeout timeout = new Timeout(Duration.create(60, TimeUnit.SECONDS));
#Override
public void preStart() {
subActorRef = getContext().actorOf(
SpringExtProvider.get(actorSystem).props(
"SubActor"), "subActor");
}
#Override
public void onReceive(Object message) throws Exception {
if (message instanceof BusinessRequestVO) {
BusinessRequestVO requestVo = (BusinessRequestVO) message;
ArrayList<Future<Object>> responseFutures = new ArrayList<Future<Object>>();
// This part of code timeout after 60seconds
responseFutures.add(ask(subActorRef,requestVo, timeout));
}
}
}
SubActor class
public class SubActor extends UntypedActor {
#Resource
#Inject
ServiceAdapter serviceAdapter;
#Override
public void onReceive(Object message) throws Exception {
try{
if (message instanceof BusinessRequestVO) {
BusinessRequestVO requestVo = (BusinessRequestVO)message
// There is no time out here so it waits synchronously
// though Main actor timeouts
ServiceResponse response = serviceAdapter.getWorkOrder(requestVo);
getSender().tell(response, ActorRef.noSender());
} catch (Exception e) {
getSender().tell(new akka.actor.Status.Failure(e), getSelf());
throw e;
}
}
}
}
Adapter Class
public class ServiceAdapterImpl implements ServiceAdapter{
public ServiceResponse getWorkOrder(BusinessRequestVO request){
// Some code here along with webservice calls
}
}
You can't as your child actor is blocking, thus cannot process any "stop" messages that the parent sends him (actors process messages one at a time before reading the next one in the mailbox).
Your best bet is to wrap the "slow" part of the child's execution inside a future that you can pipeTo the parent (see here for details).
In this way, if your timeout expires, you can have the parent send a custom "stop computing" message, and the child actor can terminate the future. See here about how to terminate a future.
But this could introduce "dirty" states in your application logic according to the specific computation that gets terminated midway through execution.
On an related note: why are you sending all n requests to the same child actor (which you made blocking)? This is equivalent to sequential execution. You should either make the child actor non-blocking or (better) create a blocking actor for each request.
EDIT: as requested by OP, added snippet. It's a pseudo code mixing scala and java, as I'm not super expert with Java syntax for futures, I mainly use it in Scala, so please adapt it a little:
if (message instanceof BusinessRequestVO) {
new Future (
BusinessRequestVO requestVo = (BusinessRequestVO)message
try {
ServiceResponse response = serviceAdapter.getWorkOrder(requestVo);
getSender().tell(response, ActorRef.noSender());
}
catch (Exception e) {
getSender().tell(new akka.actor.Status.Failure(e), getSelf());
throw e;
}
) pipeTo sender
}
And in main (see here for java's future.cancel)
if (timeout) future.cancel(true)

GWT Timer fires immediately, when running gwt-test-utils unit tests

I wrote an unit test using the gwt-test-utils framework, as described here.
The tested class internally uses a com.google.gwt.user.client.Timer (not the Java default Timer).
Only when tested, though, the Timer instance doesn't behave correctly, as it fires as soon as it is scheduled.
When I run this test
public class TimerTest extends GwtTest {
#Override
public String getModuleName() {
return "com.whatevs";
}
#Test
public void testTimer() {
final int[] counter = { 0 };
com.google.gwt.user.client.Timer t = new Timer() {
#Override
public void run() {
Log.info("firing timer");
counter[0]++; // just increase the counter
}
};
Log.info("scheduling timer");
t.schedule(1000000); // this should return immediately
Log.info("scheduling returns");
assertEquals(0, counter[0]); // the counter shouldn't yet be incremented
}
}
I get a failure
testTimer(com.whatevs.TimerTest): expected:<0> but was:<1>
And the debug output
22:37:44,075 INFO gwt-log:81 - scheduling timer
22:37:44,075 INFO gwt-log:81 - firing timer
22:37:44,075 INFO gwt-log:81 - scheduling returns
Please note that the test is run as a JUnit test, without being compiled to JavaScript first.
Am I doing something wrong, or did I just hit a bug?
Is there any other way to test such classes?
Update:
I just found out that if in the above example i call scheduleRepeating, or I reschedule the timer using schedule inside the run method, the timer fires exactly 5 times before returning control to the caller.
Something weird is going on, I just opened a bug report on gwt-test-utils.