Skip to content

Conversation

@juherr
Copy link
Member

@juherr juherr commented Jul 31, 2023

Try checkerframework and errorprone

@juherr
Copy link
Member Author

juherr commented Jul 31, 2023

@vlsi Any feedback about the 2 tools and how I added them in the build (even if I was inspired by what you did on pg-driver)?

@krmahadevan WDYT? They highlight a lot of minor issues but some potential problems too.

@krmahadevan
Copy link
Member

@juherr - This is definitely a good addition. I am yet to explore both these tools. I have already seen error prone being used by jhipster when it scaffolds a new project based on my inputs.

Couple of questions:

  • These highlight the problems in our code, but would it prevent TestNG from being used incorrectly by its consumers (especially the ones that use the TestNG apis to provide customised runners etc., ?)
  • The CI has failed, mainly because of the discrepancies in our code, which you also highlighted. So for us to adopt these two tools, I believe we would need to iterate on all the failures and then fix them right ?

@juherr
Copy link
Member Author

juherr commented Jul 31, 2023

Thanks.

These highlight the problems in our code, but would it prevent TestNG from being used incorrectly by its consumers (especially the ones that use the TestNG apis to provide customised runners etc., ?)

As I understand, yes. It provides extra data in bytecode thanks to the annotations.
The drawback is it is adding a new runtime dependency (because the annotations are stored in the bytecode).

The CI has failed, mainly because of the discrepancies in our code, which you also highlighted. So for us to adopt these two tools, I believe we would need to iterate on all the failures and then fix them right ?

To be honest, I hoped there were a bit less. That's why I sent the draft before fixing them all.

@vlsi
Copy link
Contributor

vlsi commented Jul 31, 2023

"nullability" is not trivial, so it might take some time to properly annotate and identify nullable types.
The general advice is assume "everything is not nullable by default" (==almost never put @NotNull), and annotate @Nullable where null values are allowed.

Comment on lines 11 to 12
plugins.withId("org.checkerframework") {
configure<CheckerFrameworkExtension> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plugins { id("org.checkerframework") } adds checkerframework plugin, so plugins.withId(..) is not needed here.

Something like checkerframework {...} should do.

*/
public static void assertEquals(Object[] actual, Object[] expected, String message) {
public static void assertEquals(
@Nullable Object[] actual, @Nullable Object[] expected, @Nullable String message) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it should be @Nullable Object @Nullable [] actual: nullable array of nullable elements

*/
@Deprecated
default Object newInstance(Class<?> cls) {
default Object newInstance(@NonNull Class<?> cls) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vlsi
Copy link
Contributor

vlsi commented Jul 31, 2023

In my experience, checkerframework nullability verification takes time, so I tend to activate it only when -PenableCheckerframework parameter is specified. Then checkerframework executes in a single CI job only.

See https://github.com/apache/jmeter/blob/c94db9741f0547235f9a67b1ece40389add6b742/build-logic/build-parameters/build.gradle.kts#L77 , and https://github.com/apache/jmeter/blob/c94db9741f0547235f9a67b1ece40389add6b742/build-logic/verification/src/main/kotlin/build-logic.style.gradle.kts#L42-L43 (conditional activation of .checkerframework.gradle.kts)

@juherr
Copy link
Member Author

juherr commented Jul 31, 2023

Thanks for the feedbacks @vlsi ❤️

@juherr
Copy link
Member Author

juherr commented Aug 7, 2023

Updated according to reviews.

All issues are not fixed yet.

Still 2 gradle issues: not succeeding in using the parameters plugin + not finding the way to merge package-info

@juherr juherr requested a review from vlsi August 7, 2023 07:06
* @param message the assertion error message
*/
public static void assertEquals(Object actual, Object expected, String message) {
public static void assertEquals(Object actual, Object expected, @Nullable String message) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static void assertEquals(Object actual, Object expected, @Nullable String message) {
public static void assertEquals(@Nullable Object actual, @Nullable Object expected, @Nullable String message) {

* @param message the assertion error message
*/
public static void assertEquals(Double actual, Double expected, String message) {
public static void assertEquals(Double actual, Double expected, @Nullable String message) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static void assertEquals(Double actual, Double expected, @Nullable String message) {
public static void assertEquals(@Nullable Double actual, @Nullable Double expected, @Nullable String message) {

* @param message the assertion error message
*/
public static void assertEquals(Float actual, Float expected, String message) {
public static void assertEquals(Float actual, Float expected, @Nullable String message) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static void assertEquals(Float actual, Float expected, @Nullable String message) {
public static void assertEquals(@Nullable Float actual, @Nullable Float expected, @Nullable String message) {

* @param expected the expected value
*/
public static void assertEquals(Iterator<?> actual, Iterator<?> expected) {
public static void assertEquals(@Nullable Iterator<?> actual, @Nullable Iterator<?> expected) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static void assertEquals(@Nullable Iterator<?> actual, @Nullable Iterator<?> expected) {
public static void assertEquals(@Nullable Iterator<@Nullable ?> actual, @Nullable Iterator<@Nullable ?> expected) {

*/
static boolean wasFailureDueToTimeout(ITestResult result) {
Throwable cause = result.getThrowable();
@Nullable Throwable cause = result.getThrowable();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically speaking, @Nullable should be automatically inferred for local variables, so this could probably be omitted

Suggested change
@Nullable Throwable cause = result.getThrowable();
Throwable cause = result.getThrowable();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose you're right.

It means I should not use TypeUseLocation.ALL in @DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.ALL)
Any other option I should exclude? https://checkerframework.org/api/org/checkerframework/framework/qual/TypeUseLocation.html

static List<ClassLoader> appendContextualClassLoaders(List<ClassLoader> currentLoaders) {
List<ClassLoader> allClassLoaders = Lists.newArrayList();
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
@Nullable ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@Nullable ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();

?

} else {
m.addAll(extractedMethod.getValue());
}
@Nullable Class<?> parent = clazz.getSuperclass();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@Nullable Class<?> parent = clazz.getSuperclass();
Class<?> parent = clazz.getSuperclass();


public ConstructorOrMethod(Method m) {
m_method = m;
m_constructor = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default value is null anyway, so does it make sense to assign it with null?

@vlsi
Copy link
Contributor

vlsi commented Aug 8, 2023

I would suggest merging errorprone first as it would require much fewer changes.

@juherr
Copy link
Member Author

juherr commented Aug 8, 2023

@vlsi Thanks for the review. I think your suggestion is a good strategy and I will make another PR with errorprone only.

Any idea why I'm not able to use build-parameters? The generated plugin is not found here https://github.com/testng-team/testng/pull/2941/files#diff-5bb00f6e0b0be0ec62ea3824c3888e27921683447cea9fb16bdd9f859f7881acR5

@juherr juherr mentioned this pull request Aug 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants