A small experiment on stacktraces with Coroutines;
# coroutines
c
A small experiment on stacktraces with Coroutines;
First, regular function calls:
Copy code
fun baz() {
        TODO()
    }

    fun bar() {
        baz()
    }

    fun foo() {
        bar()
    }

    test("Stack trace") {
        foo()
    }
Stack trace:
Copy code
kotlin.NotImplementedError: An operation is not implemented.
	at …$1.invoke$baz(UsernameTest.kt:15)
	at …$1.invoke$bar(UsernameTest.kt:19)
	at …$1.invoke$foo(UsernameTest.kt:23)
	at …$1.access$invoke$foo(UsernameTest.kt:12)
👀 1
Using
suspend
and
delay
:
Copy code
suspend fun baz() {
        TODO()
    }

    suspend fun bar() {
        delay(100)
        baz()
    }

    suspend fun foo() {
        bar()
    }

    test("Stack trace") {
        foo()
    }
Stacktrace:
Copy code
kotlin.NotImplementedError: An operation is not implemented.
	at …$1.invoke$baz(UsernameTest.kt:15)
	at …$1.invoke$bar(UsernameTest.kt:20)
	at …$1.access$invoke$bar(UsernameTest.kt:12)
As you can see,
foo
and everything before it have completely disappeared. I'm not saying it's wrong, after all,
foo
is indeed not in the call stack, but this is very confusing in complex examples. The problem is that the
test
call that initiated this entire example is gone from the stacktrace. If this example was more complex, I would have no way to know what actually called it at the start.
Finally, same example but running with
-ea
to enable stacktrace recovery:
Copy code
An operation is not implemented.kotlin.NotImplementedError: An operation is not implemented.
	at …$1.invoke$baz(UsernameTest.kt:15)
	at …$1.invoke$bar(UsernameTest.kt:20)
	at …$1.access$invoke$bar(UsernameTest.kt:12)
	at …$1$invoke$bar$1.invokeSuspend(UsernameTest.kt)
	at _COROUTINE._BOUNDARY._(CoroutineDebugging.kt:42)
    <…>
Caused by: kotlin.NotImplementedError: An operation is not implemented.
	at …$1.invoke$baz(UsernameTest.kt:15)
	at …$1.invoke$bar(UsernameTest.kt:20)
	at …$1.access$invoke$bar(UsernameTest.kt:12)
This is a bit better (it actually recovered the internals of the test framework in the
<…>
section) however
foo
and the test itself are still missing.
e
c
They are enabled in my last message.
c
in my test runner I’m thinking of rewriting the stack traces to make sure they always contain the test name (the test runner catches the exception anyway and it also knows what test is currently running)
c
I don't know how hard that is, but yeah that would make testing much easier