Empty benchmarks when running JMH samples in Intellij IDEA - java

I have some problem with using JMH.
So, I create an empty project in Intellij Idea, then in project structure add jmh-core jar file. Finally, try to run samples, for example
import org.openjdk.jmh.annotations.GenerateMicroBenchmark;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
public class JMHSample_01_HelloWorld {
#GenerateMicroBenchmark
public void wellHelloThere() {
// this method was intentionally left blank.
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(".*" + JMHSample_01_HelloWorld.class.getSimpleName() + ".*")
.forks(1)
.build();
new Runner(opt).run();
}
}
but result is
No matching benchmarks. Miss-spelled regexp?
Use EXTRA verbose mode to debug the pattern matching.
Process finished with exit code 0
with using verbosity(VerboseMode.EXTRA)
No matching benchmarks. Miss-spelled regexp?
Benchmarks:
Process finished with exit code 0
I tried to change output path to projectFolder\target\classes but nothing was changed.
Then I looked at the source code in the debug mode and see that resource = "/META-INF/MicroBenchmarks",urls.hasMoreElements() is false and therefore benchmarks is empty. Then I saw at the samples jar file which has MicroBenchmarks file with information about tests and work well.
So, the question is what do I do wrong?
Do I have to write information about test manually?

Please follow the instructions on JMH page to set up the benchmark project, namely:
"Make sure you tried these things before getting support:
- Archetypes provide the golden build configuration. Try to generate the clean JMH benchmark project and transplant the benchmark
there. This is important to try when upgrading to the newer JMH
versions, since the minute differences in the build configurations may
attribute to the failures you are seeing."
If you'd follow that, you will notice that you also need to add jmh-generator-annprocess as the dependency, and make sure it runs before you run any test.

Related

Maven dependencies in pom

I am unsure about what the error might be, any kind of help is appreciated.
I am trying to use - https://github.com/SpoonLabs/flacoco I clonned the repository and then
created a maven project through eclipse IDE and added the dependencies in the Pom file however when I create a main java file with the code below obtained from their video - https://www.youtube.com/watch?v=RFRyvQuwRYA&ab_channel=DavideGinelli and try to run it. It does not detect any tests. It displays the following.
[30] INFO CoverageRunner - Tests found: 0
[30] INFO CoverageRunner - Tests executed: 0
This is the code in my main.
package demoproject1;
import java.io.IOException;
import java.util.Map;
import fr.spoonlabs.flacoco.api.Flacoco;
import fr.spoonlabs.flacoco.api.result.FlacocoResult;
import fr.spoonlabs.flacoco.api.result.Suspiciousness;
import fr.spoonlabs.flacoco.core.config.FlacocoConfig;
import spoon.reflect.code.CtStatement;
public class Main {
public static void main(String[] args) throws IOException {
FlacocoConfig config = new FlacocoConfig();
config.setProjectPath("C:\\Users\\A\\Documents\\GitHub\\flacoco\\examples\\math_70"); //./examples/math_70
config.setComputeSpoonResults(true);
Flacoco flacoco = new Flacoco(config);
FlacocoResult result =flacoco.run();
Map<CtStatement, Suspiciousness> spoonMap = result.getSpoonSuspiciousnessMap();
for(Map.Entry<CtStatement, Suspiciousness> entry : spoonMap.entrySet()){
System.out.println(entry.getKey().getPosition()+":"+ entry.getValue().getScore());
}
}
}
I am unsure about what the error might be, any kind of help is appreciated.
I was also confused by this, but pretty sure you have to build the project you are trying to test. As per the paper:
"FLACOCO detects the tests to be executed and analyzed by scanning the compiled classes" (flacoco paper)
I was getting the same error, until I ran
mvn install
in the repository I was trying to test (in this case, it was examples/exampleFL1/FLtest1. Not sure if the authors just forgot to mention this explicitly (maybe they thought it would be obvious) or if they just had already built the projects they were testing. But, this is what worked for me.

Allow Evosuite to write files during test generation

Im currently trying to get Evosuite to work with JNA. Consider the following basic example:
import com.sun.jna.ptr.IntByReference;
public class Example {
public static int foo(int x) {
IntByReference c = new IntByReference(x);
if (c.getValue() == 100) {
return 100;
} else {
return 0;
}
}
}
Im running Evosuite from the command line with these options:
java32 -jar evosuite.jar -projectCP "src;E:\evosuite\test\lib\jna-5.2.0.jar" -class Example -criterion branch
Evosuite wont reach 100% branch coverage (only the trivial 33%), but notifies me with this message after the timeout:
* Permissions denied during test execution:
- java.io.FilePermission:
write C:\Users\PC\AppData\Local\Temp\jna--2025216854: 1
I found out that JNA needs to write some temp files in order to work, but Evosuite will block any atempt of file writing during test generation. I understand that this is a reasonable policy in most cases because you dont want Evosuite to write random files to your disk while generating tests for a saveFile() function, but in my case this shouldn't be a problem.
Is there a way to tell Evosuite to allow file writing during test generation or a different approach to generate tests for java programms using the JNA library?
I figured out how to run JNA without the need of writing temporary files thanks to cubrr.
copy the system specific jnidispatch.[dll, ...] file to a folder
add -Djna.boot.library.path=folder -Djna.nounpack=true to the command
Note: the jna.boot.library.path should only point to the containig folder, do not write folder/jnidispatch.
Solution to the initial question:
Setting the evosuite option -Dsandbox=false will remove most restrictions for test generation and finally allowed me to generate my tests!

Using JunitCore for tests in different projects

Background:
I am currently working on a project in eclipse that programatically executes JUnit tests that are pushed to a server.
So far everything works but I would like to know the results of the tests (specifically any failures) so I can push them out to an email. Right now the tests just output to the console but that doesn't seem to give me much output to actually use.
Right now I use the Runtime class to call the tests but that doesn't seem to have the functionality I need for getting results.
I have looked into the JUnitCore class but can't call any tests outside of the current java project.
So my main question would be how can I use JUnitCore to run junit tests in a specific JAR file? Or is there an easier way to approach this problem using a different class?
This is the only thing I've been able to get to work:
RunTests()
{
junitCore = new JUnitCore();
junitCore.run(AllTests.class);
}
But I would like to do something along the lines of this:
RunTests()
{
junitCore = new JUnitCore();
junitCore.run("C:\\$batch\\test\\hil research\\201507071307\\CommsTestRunner\\plugins\\TestSuite\\US35644.class");
}
I would appreciate any suggestions to this problem I am having. I'm an EE and was just introduced to java last month so this has been quite the challenge for me.
JUnitCore expects to read loaded classes, not class files in a JAR. Your real question is likely how to load the JAR (or directory of .class files) so it can be run.
Poke around with URLClassLoader; once you've amended the classpath appropriately, you can get a Class out of findClass and pass it into the JUnitCore methods you've found.
Since the tests might have classes that are also used by your server (but not necessarily at the same version) I would suggest not having your server directly run the tests. Instead, you can have your server start a new JVM that runs the tests. This is how IDEs like Eclipse run tests. You simply need to write a main class that has JUnit run the tests, and serializes the results on disk.
Your main class would look something like this:
public class MyRunner {
public static void main(String... args) throws IOException {
String path = System.getProperty("resultPath");
if (path == null) {
throw new NullPointerException("must specify resultPath property");
}
// Possibly install a security manager to prevent calls to System.exit()
Result result = new JUnitCore().runMain(new RealSystem(), args);
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(path)) {
out.writeObject(result);
}
System.exit(result.wasSuccessful() ? 0 : 1);
}
}
Then your server simply needs to construct a java command line with the jars that include the tests, the JUnit jar file, and a jar that contains MyRunner.

How do I fix 'Source not found' error when debugging in Eclipse, using Selenium WebDriver?

I'm practicing building a test automation framework using Selenium Webdrive in Eclipse with Java, and as part of this I'm debugging through the code I have written so that I have a full understanding (I should note that when I run my tests outside of debug mode they work fine). The issue I have is that I keep encountering 'Source not found' errors in debug mode in respect of a whole load of stuff.
I've attached a screenshot below which shows my debug window in Eclipse, and shows an example of one of the errors.
So, the situation is that I have my TestRunner class from where I am running my tests (see code below)
package dataStructureModel;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.firefox.FirefoxDriver;
public class TestRunner {
public static void main(String[] args) {
FirefoxDriver driver = new FirefoxDriver();
List<iTest> tests = new ArrayList<iTest>();
// adding first test
tests.add((iTest) new DragDefaultTest001());
// adding second test
tests.add((iTest) new ColorCheckTest002());
BREAKPOINT HERE!
for(int i = 0; i < tests.size() ; i++)
{
iTest currentTest = tests.get(i);
currentTest.testSetup(driver);
boolean testResult = currentTest.runTest();
if(testResult)
{
System.out.println(currentTest.testName() + " test passed.");
}
else
{
System.out.println(currentTest.testName() + " test failed.");
}
currentTest.testCleanup();
}
}
}
I've set a breakpoint at the 'for' loop to iterate through my tests (I've not attached the code, given that as mentioned earlier, the tests do run). The Firefox browser loads up and I start stepping through and all looks good. Then I hit one of these 'Source not found' errors', of which there are many. I've attached a screenshot here, which gives an example....http://i.imgur.com/aDxCAX0.png
I know it asks to 'Edit Source Lookup Path', but I'm not sure what I should be referencing? As far as I'm aware I've attached all the selenium jar files, so I'm not sure where I'm going wrong.
This needs selenium-jar SOURCE files. In case you do no intend to see internals of Selenium Jars(which is a rare case), then just Step Over(F6) instead of Step Into(F5)
Hope this helps!

Is *this* really the best way to start a second JVM from Java code?

This is a followup to my own previous question and I'm kind of embarassed to ask this... But anyway: how would you start a second JVM from a standalone Java program in a system-independent way? And without relying on for instance an env variable like JAVA_HOME as that might point to a different JRE than the one that is currently running. I came up with the following code which actually works but feels just a little awkward:
public static void startSecondJVM() throws Exception {
String separator = System.getProperty("file.separator");
String classpath = System.getProperty("java.class.path");
String path = System.getProperty("java.home")
+ separator + "bin" + separator + "java";
ProcessBuilder processBuilder =
new ProcessBuilder(path, "-cp",
classpath,
AnotherClassWithMainMethod.class.getName());
Process process = processBuilder.start();
process.waitFor();
}
Also, the currently running JVM might have been started with some other parameters (-D, -X..., ...) that the second JVM would not know about.
I think that the answer is "Yes". This probably as good as you can do in Java using system independent code. But be aware that even this is only relatively system independent. For example, in some systems:
the JAVA_HOME variable may not have been set,
the command name used to launch a JVM might be different (e.g. if it is not a Sun JVM), or
the command line options might be different (e.g. if it is not a Sun JVM).
If I was aiming for maximum portability in launching a (second) JVM, I think I would do it using wrapper scripts.
It's not clear to me that you would always want to use exactly the same parameters, classpath or whatever (especially -X kind of stuff - for example, why would the child need the same heap settings as its parents) when starting a secondary process.
I would prefer to use an external configuration of some sort to define these properties for the children. It's a bit more work, but I think in the end you will need the flexibility.
To see the extent of possible configuration settings you might look at thye "Run Configurations" settings in Eclipse. Quite a few tabs worth of configuration there.
To find the java executable that your code is currently running under (i.e. the 'path' variable in your question's sample code) there is a utility method within apache ant that can help you. You don't have to build your code with ant - just use it as a library, for this one method.
It is:
org.apache.tools.ant.util.JavaEnvUtils.getJreExecutable("java")
It takes care of the sort of special cases with different JVM vendors that others have mentioned. (And looking at the source code for it, there are more special cases than I would have imagined.)
It's in ant.jar. ant is distributed under the Apache license so hopefully you can use it how you want without hassle.
Here's a way that determines the java executable which runs the current JVM using ProcessHandle.current().info().command().
The ProcessHandle API also should allow to get the arguments. This code uses them for the new JVM if available, only replacing the current class name with another sample class. (Finding the current main class inside the arguments gets harder if you don't know its name, but in this demo it's simply "this" class. And maybe you want to reuse the same JVM options or some of them, but not the program arguments.)
However, for me (openjdk version 11.0.2, Windows 10), the ProcessInfo.arguments() is empty, so the fallback else path gets executed.
package test;
import java.lang.ProcessBuilder.Redirect;
import java.lang.management.ManagementFactory;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestStartJvm {
public static void main(String[] args) throws Exception {
ProcessHandle.Info currentProcessInfo = ProcessHandle.current().info();
List<String> newProcessCommandLine = new LinkedList<>();
newProcessCommandLine.add(currentProcessInfo.command().get());
Optional<String[]> currentProcessArgs = currentProcessInfo.arguments();
if (currentProcessArgs.isPresent()) { // I know about orElse, but sometimes isPresent + get is handy
for (String arg: currentProcessArgs.get()) {
newProcessCommandLine.add(TestStartJvm.class.getName().equals(arg) ? TargetMain.class.getName() : arg);
}
} else {
System.err.println("don't know all process arguments, falling back to passed args array");
newProcessCommandLine.add("-classpath");
newProcessCommandLine.add(ManagementFactory.getRuntimeMXBean().getClassPath());
newProcessCommandLine.add(TargetMain.class.getName());
newProcessCommandLine.addAll(List.of(args));
}
ProcessBuilder newProcessBuilder = new ProcessBuilder(newProcessCommandLine).redirectOutput(Redirect.INHERIT)
.redirectError(Redirect.INHERIT);
Process newProcess = newProcessBuilder.start();
System.out.format("%s: process %s started%n", TestStartJvm.class.getName(), newProcessBuilder.command());
System.out.format("process exited with status %s%n", newProcess.waitFor());
}
static class TargetMain {
public static void main(String[] args) {
System.out.format("in %s: PID %s, args: %s%n", TargetMain.class.getName(), ProcessHandle.current().pid(),
Stream.of(args).collect(Collectors.joining(", ")));
}
}
}
Before ProcessHandle was added in Java 9, I did something like this to query the current JVM's command-line:
Let the user pass or configure a "PID to command-line" command template; under Windows, this could be wmic process where 'processid=%s' get commandline /format:list.
Determine PID using java.lang.management.ManagementFactory.getRuntimeMXBean().getPid().
Expand command template; execute; parse its output.

Categories