Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass "illegal-access=deny" to unit test's JVM args using Gradle java plugin?

I have a test that correctly fails with an InaccessibleObjectException when I run it with JVM args --illegal-access=deny in Eclipse. I want it to fail the same way when I run gradle check.

I tried the solution from How to pass args to JVM which runs tests with Gradle:

# build.gradle
apply plugin: 'java'

test {
  jvmArgs '--illegal-access=deny'

  # also tried
  # jvmArgs('--illegal-access', 'deny')
  # jvmArgs '-Dillegal-access=deny'
}

The test passed instead of failing. I did see tests saying they were dirty because jvmArgs had changed.

Here's the JUnit test that fails to fail. Sorry it doesn't have an "expectedException" set up, but it does throw when run with --illegal-access=deny from Eclipse.

import static org.junit.Assert.fail;

import java.lang.reflect.Field;

import org.junit.Test;


public class IllegalAccessTest {
  @Test
  public void testIllegalAccess() throws NoSuchFieldException, SecurityException {
    Field libraries = ClassLoader.class.getDeclaredField("loadedLibraryNames");
    System.out.println("About to set accessible");
    libraries.setAccessible(true);
    fail("Should fail before getting here when run with --illegal-access=deny");
  }
}

The output from this test when run with Gradle shows -Dillegal-access=deny is getting passed to Gradle, just not causing the test to fail:

Starting process 'Gradle Test Executor 33'. Working directory: xxx Command: /usr/java/jdk-11.0.4/bin/java -Dillegal-access=deny -Dorg.gradle.native=false -javaagent:xxx,jmx=false @/tmp/gradle-worker-classpath17509364376879385105txt -Xmx512m -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle Test Executor 33'
Successfully started process 'Gradle Test Executor 33'

x.y.z.IllegalAccessTest  > testIllegalAccessQS STANDARD_OUT
    About to set accessible

x.y.z.IllegalAccessTest  > testIllegalAccessQS FAILED
    java.lang.AssertionError: Should fail before getting here when run with --illegal-access=deny
        at org.junit.Assert.fail(Assert.java:88)
        at x.y.z.IllegalAccessTest.testIllegalAccessQS(IllegalAccessTest.java:36)

The error message when run with Eclipse is the correct

java.lang.reflect.InaccessibleObjectException: Unable to make field private static final java.util.Set java.lang.ClassLoader.loadedLibraryNames accessible: module java.base does not "opens java.lang" to unnamed module @6b9651f3
like image 719
Noumenon Avatar asked Jan 16 '20 16:01

Noumenon


3 Answers

The documentation for Test tasks reads: List<String> jvmArgs:

The extra arguments to use to launch the JVM for the process. Does not include system properties and the minimum/maximum heap size.

And there is nothing else, which would make sense - therefore this might be:

test.jvmArgs = ["--illegal-access=deny"]

Possibly with or without -- or -. Be aware that JUnit 5 may behave differently.

like image 152
Martin Zeitler Avatar answered Nov 17 '22 04:11

Martin Zeitler


As discussed in the question comments, a minimal reproducible example would help in tracking down the issue. Given that it wasn’t possible to provide one, maybe it’ll help to have a minimal example that works.

Minimal Working Setup

This is the complete setup (excluding the Gradle 5.6.2 Wrapper files):

.
├── build.gradle
└── src
    └── test
        └── java
            └── IllegalAccessTest.java

build.gradle

plugins {
    id 'java'
}

repositories {
    jcenter()
}

dependencies {
    testImplementation 'junit:junit:4.10'
}

test {
    jvmArgs '--illegal-access=deny'
}

src/test/java/IllegalAccessTest.java

exactly the same as given in the question

Testing if it Works

Running ./gradlew test yields the expected java.lang.reflect.InaccessibleObjectException at line 13 of src/test/java/IllegalAccessTest.java:

> Task :test FAILED

IllegalAccessTest > testIllegalAccess FAILED
    java.lang.reflect.InaccessibleObjectException at IllegalAccessTest.java:13

1 test completed, 1 failed

FAILURE: Build failed with an exception.

I have used OpenJDK 11.0.5 in this test.

A Note on Different Methods for Changing the Test JVM Arguments

If the following makes a difference (as suggested in this comment)

test.jvmArgs = ["--illegal-access=deny"]

compared to

test.jvmArgs '--illegal-access=deny'

then you may have set JVM args in multiple locations which interfere with each other. The former replaces all previously set JVM args with only --illegal-access=deny while the latter only adds the --illegal-access=deny option.

like image 26
Chriki Avatar answered Nov 17 '22 06:11

Chriki


Please try this. This is how I pass JVM arguments to my tests from gradle and it works.

test {
    jvmArgs '-Dillegal-access=deny'
}
like image 2
Julian Avatar answered Nov 17 '22 05:11

Julian