Thursday, January 20, 2022

InvalidTestClassError - No runnable methods

Recently I encountered an interesting error while running a unit test. This test was passing from my Intellij IDE, but was failing from the maven. Below is the error I got from maven
[ERROR] com.test.SampleTest.initializationError  Time elapsed: 0 s  <<< ERROR!
org.junit.runners.model.InvalidTestClassError: 
Invalid test class 'com.test.SampleTest':
  1. No runnable methods
The error was coming because my test class has following
  • extending BaseTest that extends the junit's TestCase.
  • running my test using @Test from org.testng.annotations.
  • using @RunWith(JMockit.class)
 
@RunWith(JMockit.class)
class SampleTest extends BaseTest {

  @BeforeClass // testng
  public void setUp(){
    super.setUp();
  }
  ... then test cases
}

If I run the test without JMockit removes the No runnable methods error. But it causes few other errors as my test was relying on mocked data. So I removed all the testng @Test and replaced it with junit @Test.

Then it raised another issue, BaseTest class already has a setUp() method which is not static, and I can't use it from a static method (@BeforeClass for setUp()). So I pushed this super.setUp() inside the @Before which runs every time the test runs. But I added a small trick to load it only once.

@RunWith(JMockit.class)
class SampleTest extends BaseTest {

  private boolean initialised = false;
    
  @Before // junit
  public void setUp(){
    if(!initialised){
      super.setUp();
      initialised = true;
    }
  }
  ... then test cases
} 
Another thing I tried was adding @Ignore for the BaseTest so that junit avoids it. But that didn't work for me.

I was using the following command to run it from maven
mvn verify -Dtest=SampleTest -DfailIfNoTests=false

Thursday, January 6, 2022

Map with expiry time in Java

Map in Java holds the value as key value pair. And it keeps the data there until the end of the application lifecycle. But sometimes a case could arise where you need to use the map with an expiry time, after which your particular entry will be removed. For that purpose here are a few examples from the various libraries of Java.

1. PassiveExpiringMap



Apache collection has a simple implementation for expiring hashmap which is PassiveExpiringMap. This uses the implementation of Map underneath. We just need to construct the object with a given expiry time after which an entry will be removed from the map.

Maven dependency:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>


Code snippet to show the usage. In this example we are setting the expiry time 1000 milliseconds, and adding entries to the map every 500 milliseconds.

    
    int expiryInMills = 1000;
    PassiveExpiringMap<String, Integer> map = new PassiveExpiringMap<>(expiryInMills);
    for (int i = 0; i < 10; i++) {
        map.put(String.valueOf(i), i);
        System.out.println(map.keySet());
        Thread.sleep(500);
    }


Pros:
  • Usage is very simple.
  • Comes with Apache collection which is sometimes available in the project.


Cons:
  • Not thread safe.
  • Removes expired values only when the get(), keySet(), or size() methods are called. More precisely, if we only do put() and do nothing, nothing will be removed from the map.


2. Guava cache



This is a Cache implementation that comes with the Guava. The main purpose of this is actually to serve as an in-memory cache. It has many features related to caching but among all two features are interesting (expire after write, and expire after access). For our needs we can use the expireAfterWrite() option which we can use to set the expiry time for an entry. Once that is set, any particular entry having that time will be removed.

Maven dependency:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>10.0.1</version>
</dependency>


Code snippet to show the usage. In this example we are using expiry time 1000 milliseconds and adding an entry to the cache after 500 milliseconds. We are setting the expiry time through expireAfterWrite().

    int expiryInMills = 1000;
    LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
            .expireAfterWrite(expiryInMills, TimeUnit.MILLISECONDS)
            .build(
                    new CacheLoader<String, Integer>() {
                        public Integer load(String key) {
                            return 1;
                        }
                    });
    for (int i = 0; i < 10; i++) {
        cache.put(String.valueOf(i), i);
        System.out.println(cache.asMap().keySet());
        Thread.sleep(500);
    }


Pros:
  • Implementation uses the concurrent hashmap underneath which is thread safe.
  • Comes with features for in-memory cache.


Cons:
  • Designed for Cache, and could be heavy if those features are not needed.
  • I think the latest version is still in beta. Otherwise none.


3. Caffeine Cache



Caffeine cache was introduced after being inspired by the Guava cache (but adding few features and improvements). For our purpose we don't need it. We only need the expiring entries from the map after the given time.

Maven dependency:

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.0.5</version>
</dependency>


Code snippet to show the usage. The usage is similar to the Guava cache.

    
    int expiryInMills = 1000;
    Cache<String, Integer> cache = Caffeine.newBuilder()
            .expireAfterWrite(expiryInMills, TimeUnit.MILLISECONDS)
            .build();

    for (int i = 0; i < 10; i++) {
        cache.put(String.valueOf(i), i);
        System.out.println(cache.asMap().keySet());
        Thread.sleep(500);
    }


Pros:
  • Similar to Guava cache. And comes with more features which Guava is missing.


Cons:
  • Designed for Cache, and could be heavy if those features are not needed.


Output



For all the above code snippet, the output is same, and it is

[0]
[1, 0]
[1, 2]
[3, 2]
[3, 4]
[5, 4]
[5, 6]
[7, 6]
[7, 8]
[8, 9]


Tuesday, January 4, 2022

Analyse large heap dump using Eclipse MAT

It is easy to analyse a heapdump when the dump file size is reasonable. But to analyse a large heap dump (specially a dump from production) is not straightforward. I personally prefer the Eclipse Memory Analyser. When I try to load the large dump using the UI it just get crashed. Here are the steps I am showing how to analyse the heap from commandline and then view it using the UI.

Generate index from command-line

My heap dump size is approximately 30gb. To generate index and I provide 22gb memory from commandline. My Java version is 17 (Eclipse requires version 11 or later). And I executed the command in Mac which has 32gb memory. Below is the command.

/Applications/mat.app/Contents/MacOS/MemoryAnalyzer -consolelog -application org.eclipse.mat.api.parse "/Heapdump/analyse.dump" -vm /jdk-17.0.1.jdk/Contents/Home/bin/java -vmargs -Xmx22g -XX:-UseGCOverheadLimit
Above command takes several minutes to finish and below is the output for my heap dump.
WARNING: A terminally deprecated method in java.lang.System has been called
WARNING: System::setSecurityManager has been called by org.eclipse.osgi.internal.framework.SystemBundleActivator (file:/Applications/mat.app/Contents/Eclipse/plugins/org.eclipse.osgi_3.16.300.v20210525-1715.jar)
WARNING: Please consider reporting this to the maintainers of org.eclipse.osgi.internal.framework.SystemBundleActivator
WARNING: System::setSecurityManager will be removed in a future release
Task: Parsing analyse.dump
[Task: Parsing /Heapdump/analyse.dump
[
Subtask: Scanning /Heapdump/analyse.dump
[....................
[INFO] Wrote threads call stacks to /Heapdump/analyse.dump.threads
[....................
[INFO] Heap /Heapdump/analyse.dump.dump contains 263,511,984 objects
[....................
Subtask: Extracting objects from /Heapdump/analyse.dump.dump
[................................................................................Task: Removing unreachable objects
[
Subtask: Searching for unreachable objects
[
Subtask: Marking reachable objects
[.
Subtask: Re-indexing objects
[.
[INFO] Removed 174,619 unreachable objects using 14,634,072 bytes
[..
Subtask: Re-indexing classes
[...
Subtask: Writing /Heapdump/analyse.dump.idx.index
[....
Subtask: Writing /Heapdump/analyse.dump.o2c.index
[.....
Subtask: Writing /Heapdump/analyse.dump.a2s.index
[......
Subtask: Re-indexing outbound index
[.......
Subtask: Writing /Heapdump/analyse.dump.inbound.index
[........
Subtask: Writing /Heapdump/analyse.dump.outbound.index
[.........
Subtask: Writing /Heapdump/analyse.dump.o2hprof.index
[.........Task: Calculating Dominator Tree
[
Subtask: Dominator Tree calculation
[
Subtask: Depth-first search
[....................
Subtask: Computing dominators
[..............................................
Subtask: Calculate retained sizes
[............................................................
Subtask: Create dominators index file
[................................................................................]

Load generated index into UI

This command basically generates several index files ends with analyse.outbound.index and a single file analyse.threads. As you have the index generated, it would be much easier to load the dump into the UI. But before doing that you need to point Eclipse MAT to a java that is version 11 or greater, and also provide some memory to it. I provide 22gb memory to it. Here is you you can configure. 1. Open the /Applications/mat.app/Contents/Info.plist and update the -vm path.
<!-- To use a specific Java version (instead of the default) uncomment the following option and 
		edit it to add a VM. Installed VMs can be found via $/usr/libexec/java_home -V
		<string>-vm</string><string>/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/bin/java</string>
	-->
<string>-vm</string><string>/jdk-17.0.1.jdk/Contents/Home/bin/java</string>
2. Update -vm in /Applications/mat.app/Contents/Eclipse/MemoryAnalyzer.ini. Make sure you put it before the -vmargs. And also update how much memory you want to put. Here is mine:
-startup
../Eclipse/plugins/org.eclipse.equinox.launcher_1.6.200.v20210416-2027.jar
--launcher.library
../Eclipse/plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.2.200.v20210527-0259
-vm /jdk-17.0.1.jdk/Contents/Home/bin/
-vmargs
-Xmx22g
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XstartOnFirstThread
All set! now open your Eclipse MAT, click Open a Heap Dump, and then select the analyse.dump to open. This will take a few minutes to generate a report which later you can analyse. You could generate the report from the command line too. But as my UI could do it for me I didn't try the commandline.


Notes:

If you do not provide the -vm from the commandline you'd end up with error like below:
2022-01-04 19:08:16.855 MemoryAnalyzer[23910:1364729] Cannot find executable for CFBundle 0x7f88b3508420 </Library/Internet Plug-Ins/JavaAppletPlugin.plugin> (not loaded)
Image showing error: The JVM shared library "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/../lib/server/libjvm.dylib" does not contain the JNI_CreateJavaVM symbol.



If you do not provide the -vm in Info.plist, You'd see the same error while opening the Eclipse MAT ui.

Sunday, November 26, 2017

Get function name programaticaly - Python

This little piece of code will help you to get the function name programatically. This is very helpful when you are implementing the debugging prints from your program.


import sys

def new_function():
    function_name = sys._getframe().f_code.co_name
    print function_name

new_function()



You of course can write the function name manually(function_name="new_function"). But that case if you change the function's name, you have to change the string as well from the variable function_name.


Wednesday, November 27, 2013

SyntaxError: Non-ASCII character '\xe9' in file on line 22

The Error:

SyntaxError: Non-ASCII character '\xe9' in file test.py on line 22, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details


This is mainly occurred when you are trying to print the unicode text into the console. Basically the error itself has the solution. Browsing the link will show you what exactly have to be done.


Just writing the below code at the very first or the second line at the script. This will set the encoding of the console and will evade the error you are encountering.


# -*- coding: utf-8 -*-


How to display contents from a file into textarea - PHP

How to display contents from a file into the textarea of HTML?

This is very easy and slightly tricky. Here is the PHP code:

    print '<textarea>';
    include($_some_file_name);
    print '</textarea>';


Basically you are including the whole contents from the file into the PHP source which later rendered as HTML. Its just a tricky but effective solution.


Saturday, November 9, 2013

Upgrading Python in Linux without YUM

Upgrading the Python at Linux box is slightly risky as the Yum is heavily dependent upon the Python. You have to be very careful while doing this on linux.


I was having the Python 2.4.3 as default with my linux installation. To upgrade the Python to 2.7.3 I have followed the below instructions. It was simple. Just downloading, compiling and installing.


Notes: Make sure you have the linux development tools, gcc, zlib and similar things are already installed. Otherwise you can not perform the following tasks.


1) Download the Python.
wget http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tar.bz2



2) Extract the zip file.
tar xf Python-2.7.3.tar.bz2



3) Enter inside the extracted directory.
cd Python-2.7.3



4) Configuring the installation.
./configure --prefix=/usr/local



5) Make and install at the same time.
make && make altinstall



6) Add symbolic link in /usr/local/bin.
ln -s /usr/local/bin/python2.7 /usr/local/bin/python



That's it. Enjoy your upgraded Python!


InvalidTestClassError - No runnable methods

Recently I encountered an interesting error while running a unit test. This test was passing from my Intellij IDE, but was failing from the ...