Our thread dumps have a lot of unnamed threads. To make the Java thread dump analysis easier in the future, we'd like to ensure that any Thread has gotten a name (before it is started via start()):
MyThreadImpl myThread = new MyThreadImpl(); // extends Thread
myThread.setName("Descriptive name"); // ArchUnit should check this
myThread.start();
// ....
Thread anotherThread = new AnotherThread();
anotherThread.start(); // should raise violation, #setName was not called
// ...
new ThirdThreadImpl().start(); // in a perfect world, this also might be violated
I guess the test can look like this:
@ArchTest
public static final ArchRule ANY_THREAD_SHOULD_CALL_SET_NAME =
fields().that(extendThread())
.should(callMethodSetName());
The predicate to locate any field extending Thread would look like this from my understanding:
private static DescribedPredicate<? super JavaField> extendThread() {
return new DescribedPredicate<JavaField>("extend Thread") {
@Override
public boolean test(JavaField javaField) {
return javaField.getRawType().isAssignableTo(Thread.class);
}
};
}
I am not able to complete the condition though and I also have doubts if I even should start the rule with fields()
or with methods()
or classes()
. Because the example with new ThirdThreadImpl().start()
does not include a fields definition.
Can anyone help me out with this? ArchUnits documentation focuses on layers and naming rules and I don't understand the possible approach in here.
p.s. imports are taken from
import com.tngtech.archunit.*;
ArchUnit (currently in version 1.3.0) does not allow you to track individual objects, so you cannot test whether setName
was called on a Thread
instance before it is start
ed.
Do you really have MyThreadImpl
and AnotherThread
implementations? If not, you could maybe work around the issue by preventing the use of unnamed Thread
constructors.