Wednesday May 31, 2006 Testing memory leaks with assertGC
I was talking about assertSize in one of previous entry about testing. NbTestCase class contains more useful methods. Today I will be talking about assertGC method. The assertGC method tests tries to run garbage collect with different methods and then scan if exists path to reference in memory by using insane library. Look at simple example:
public class LeakTest extends NbTestCase {
public LeakTest(java.lang.String testName) {
super(testName);
}
public void testLeak() {
String obj = new String("test1");
WeakReference ref = new WeakReference(obj);
obj = null;
assertGC("pass",ref);
obj = new String("test2");
ref = new WeakReference(obj);
assertGC("fails",ref);
}
public static Test suite() {
TestSuite suite = new NbTestSuite(LeakTest.class);
return suite;
}
}
First asertGC passed because in JVM exists only WeakReference for object String("test1"). The second assertGC failed because the reference obj holds String("test2").
Posted by xzajo ( May 31 2006, 02:46:35 PM CEST ) Permalink Comments [16]Jiri Skrivanek updated documentation how to use XTest framework in NetBeans IDE. XTest is extension of JUnit 3.x. It was designed to help develops tests for NetBeans platform. The flash demo is available here. Updated tutorial for XTest is on this page.
Many people in NetBeans asked me why not to switch to TestNG with annotations. To tell you truth xtest already has more features than TestNG now. Xtest has also few disadvantages. It is difficult to configure it. The authors of xtest never wrote tests. Only Jiri Skrivanek, the last owner, writes tests. Maybe he is the right person who fix problems with xtest.
Why we still use Xtest for testing NetBeans? There are few reasons:
Yesterday I was speaking with Stanislav Albrecht. He is working on fullscreen mode feature in NetBeans. He showed me it on Windows L&F. The feature has not finished yet. He need to implement full sreen mode feature also for others Look&Feels. But I was impressed. I use fullscreen mode in other application on my notebook. It saves workspace on my display. I can use it now also in NetBeans.
UI spec with flash demo for this feature is available on this page. Stanislav gave me a build with this feature for testing. I will show few screenshots. On the first screenshot is NetBeans in normal mode.
Two actions are highlighted in the screenshot. The first is in main menu. It shows NetBeans in full screen mode. The second is represented by icon in the right corner of window. It maximizes the window in NetBeans layout. The other windows are slided off - minimized by window sliding feature. I clicked on both actions. The result is on the screenshot below.
The main menu will be hidden in final version. This feature will be also available for application based on RCP. Developers don't need to change their applications. They only need to rebuild their applications with new NetBeans platform. The full screen action and maximize window button will be added automatically.
Posted by xzajo ( May 25 2006, 12:31:29 PM CEST ) Permalink Comments [11]Test size of your data structures in Unit Test
Petr Nejedly invented interesting tool for measuring memory usage of data structures on java heap. Name of the tool is Insane. Pages of the tools are here. It uses Java introspection to traverse all fields and references in graph of data structure. It allows to exclude traversing for specified references. Insane was integrated with NBJunit library. NBJunit is extension of Junit 3.x. It was designed in order to test NetBeans IDE. In this article I try show power of Insane library inside NBJunit.
NBTestCase class is supper class of for NetBeans test. It extends from Junit TestCase. The NBTestCase contains assertSize methods for testing size of java structures. For example we want to measure size of NumList class:
public static class NumList {
public int num;
public NumList next;
};
A instance of the class takes 16 bytes on the heap on 32bit virtual machine. A simple test for this structure can look like this:
public void testA() {
NumList item = new NumList();
// 1. test one instance
assertSize("NumList a",16,item);
// 2. test size of instances in collection
assertSize("NumList a",Collections.singleton(item),16);
NumList item2 = new NumList();
item.next = item2;
// 3. test linked structure
assertSize("NumList a",Collections.singleton(item),32);
// 4. ignore the item2 references
assertSize("NumList a",Collections.singleton(item),16,new Object[]{item2});
}
The test passed when the size of the structure doesn't exceed the defined limit (16 or 32 bytes). Interesting is use case on line number four
assertSize("NumList a",Collections.singleton(item),16,new Object[]{item2});
The last parameter tells that the measurement won't traverse through item2 reference. It is very useful when we measure only subset of complicated structure.
The test passed. Why the instance of NumList takes 16 bytes in memory of 32bit JVM?
public static class NumList {
public int num;
public int num2;
public NumList next;
};
We run the test again. The test fails with message:
Testcase: testA(MemoryTest): FAILED
NumList a: leak 8 bytes over limit of 16 bytes
MemoryTest$NumList: 1, 24B
junit.framework.AssertionFailedError: NumList a: leak 8 bytes over limit of 16 bytes
MemoryTest$NumList: 1, 24B
at org.netbeans.junit.NbTestCase.assertSize(NbTestCase.java:1108)
at org.netbeans.junit.NbTestCase.assertSize(NbTestCase.java:1065)
at org.netbeans.junit.NbTestCase.assertSize(NbTestCase.java:1050)
at org.netbeans.junit.NbTestCase.assertSize(NbTestCase.java:1039)
at MemoryTest.testA(MemoryTest.java:28)
Instance takes 24 bytes in memory now. How is it possible if the int type tales 4 bytes in memory? Yes it takes four bytes. The instance takes 24 bytes on heap because the size of java object is aligned to 8 bytes. So we will fix the test for new NumList version.
public void testA() {
NumList item = new NumList();
assertSize("NumList a",24,item);
assertSize("NumList a",Collections.singleton(item),24);
NumList item2 = new NumList();
item.next = item2;
assertSize("NumList a",Collections.singleton(item),48);
assertSize("NumList a",Collections.singleton(item),24,new Object[]{item2});
}
The test passed now. The instance is aligned to 8 bytes as I wrote. Why to no try add one more varible to TestNum structure? The new version is below.
public static class NumList {
public int num;
public int num2;
public int num3;
public NumList next;
};
This version does't need more memory than the previous. We can check it by running the test. Yes, the test passed now. Isn't combination of Insane ane NbJUnit great idea?
Posted by xzajo ( May 23 2006, 08:51:14 PM CEST ) Permalink Comments [38]GlassFish project quality team chose TestNG framework for testing. Why did they make the decision? They compared the both tools in this document.
It looks like war Eclipse versus NetBeans. NetBeans dominate five years ago in Java IDE's. NetBeans had few dessign problems and almost no innovation. Therefore Eclipse eclipsed NetBeans. But the situation is quite different now. There was many new features in NetBeans 5.0. Everything is in one pack (J2SE, J2EE, J2ME, profiler). The NetBeans team is focused on usability. Many 3rd party plugins are available on nbextras.org NetBeans 5.5 beta with EJB support has been released. Completely new java editor will be in NetBeans 6.0.
. And eclipse? Yes there exists many plugins for eclipse. But with different UI and the plugins are not compatible. No it is no end of Eclipse. It's challenge for Eclipse team. They also need to innovate. So who wins the war between two java opensource IDE's? I think the user. He will have two powerful java IDE's. Isn't great to have two different opensourced java IDE's in the world?Back to subject TestNG versus JUnit 4. What is idea of TestNG? I think:
Mocking final classes with BCEL, java.lang.instrument and EasyMock
I've introduced EasyMock library in previous entry of testing category. I read in documentation of EasyMock that final methods cannot be mocked. I've found solution of this problem for testing with Jmock library. Bytecode of the class is changed before the class is loaded. The solution also works for EasyMock. I'll describe how to do it in next paragraphs.
The Byte Code Engineering Library (BCEL) library provide simple way how to navigate and change bytecode of java classes. I used this library in order to remove final flag from classes. It is only few lines by using this library.
Java.lang.instrument provides services that allow Java programming language agents to instrument programs running on the JVM. Nice article about it is here. I used java.lang.instrumnet for changing bytecode during classloading.
Example with removing final flag is below. Transf class is implementation of java.lang.instrument service. It is not difficult to add removing of final flag for methods of class to code. I created this example to demonstrate how powerful is java.lang.instrument service.
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
....
public class Transf implements ClassFileTransformer {
public byte[] transform(ClassLoader loader,
String className,
Class redefiningClass,
ProtectionDomain domain,
byte[] bytes) throws IllegalClassFormatException {
try {
ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes),className);
JavaClass clazz = parser.parse();
clazz.setAccessFlags(clazz.getAccessFlags() & (~Constants.ACC_FINAL ));
bytes = clazz.getBytes();
System.out.println("Transformed Class: " + className);
} catch (ClassFormatError ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
return bytes;
}
}
To initialize the class patching agent it is necessary to create premain class:
public class SimpleMain {
public static void premain(String agentArguments, Instrumentation instrumentation) {
instrumentation.addTransformer(new Transf());
}
}
The referece of the premain class is specified in MANIFEST.mf of build jar with java agent.
Manifest-Version: 1.0 Premain-Class: mypackage.SimpleMainWhen we run tests we need to say java where the java agent service is located by using -javaagent parameter.
java -javaagent:classpatching.jar ...Posted by xzajo ( May 13 2006, 03:00:00 PM CEST ) Permalink Comments [8]
SourceForge - CVS server down for a week and up with different host name!
CVS server is many times down. The last was on the end of last week. The server is up again today. But with a small difference. The host name of my cvs server has been chaged. What's mean for me? I was developing for a week without commit. I will have to checkout the cvs repository to other folder on my local disk. Copy changed files from old cvs checkout to new folder. SourceForge have many other problems. I started lookong for new opensource provider. When I find them I'll move the nbxdoclet project.
Posted by xzajo ( May 13 2006, 01:10:23 AM CEST ) Permalink Comments [12]Hibernate plugin for NetBeans updated Today was updated Hibernate plugin for NetBeans 5.x. It's is available on its update center . Few bugfixes and new features were integrated:
Customizing velocity templates of wizards.
All templates are written in Velocity language (I would like to switch to Freemaker engine in future. FreeMaker is more powerful than Velocity.). The Templates browser is available from main menu ( Window|Show Velocity Teplates). The templates can be changed in editor. Opened editor with hibernate11relation is below on the screenshot. If someone know how to improve the code of templates he can send me his new version.
HQL wizard for EJB3 query language. UI is the same like for HQL wizard. Only the wizard is available in code completion of facade for EJB3 POJO.
User hibernate properties for hibernate project extension. The Hibernate project extension generated default hibernate properties file. It was difficult to change the properties manually. So I decided to merge the generated properties with new user properties. The user properties are available from popup of Hibernate project extension.
Creating Hibernate util when the facade is created. There was a usability problem. When user wanted to create new hibernate facade the HibernateUtil class had to already created. The HibernateUtil wizard is now shown when the HibernateUtil is not presented in project on creating facade from code completion. The facade class is automatically opened in editor after creating. It's expected behaviour, I hope.
Posted by xzajo ( May 12 2006, 04:44:29 PM CEST ) Permalink Comments [11]Test Patterns In Java™ Technology Development on Java One
Are you going on Java One? Don't forget on Test Patterns In Java™ Technology Development session.
Three architects of NetBeans (Jesse Glick, Jaroslav Tulach, Milos Kleint) will be talking about their experiences with test driven development. To tell you truth, these guys save me a lot of time in my work. Yes, they are careful and write tests whether it is possible. Almost no regression is in their code. I than can cover more features as QA representative.
I tell you a success story with test driven development. Jaroslav Tulach is one of the NetBeans fathers. I remember times when he started to write tests. He wrote API of NetBeans. Many developers dependent on his code. Before four years every one in NetBeans were afraid of his commits. A small change in code on which depends many developers caused the break of NetBeans build. But now he write also a lot of code. But the code is already tested with unit tests. And the code is really stable. Every one writes code with mistake. With test the code contains a little count of bugs and we are able to catch regressions earlier with daily tests runs.
I learn from Jaroslav's and Jesse's code a lot of useful testing pattern. Therefore I recommend the session.
Testing is an important part of software development. Effective testing is a key factor in reducing total cost of maintenance of any application over its lifetime. It reduces the cost and time of development and can increase savings on quality assurance. Knowing when to invest in better design, in postdevelopment quality assurance, in manual tests, or in automatic testing forms a basic difference between successful and unsuccessful software projects in these tough and competitive days.
This presentation starts with general motivation and presents automatic tests as a form of functional specification. It then quickly delves deep down into hard-core JUnit test examples showing various forms of regression tests verifying algorithm complexity, memory management, data structure sizes, deadlocks, race condition behavior and tests randomly generating new test cases, simulating user clicks in the UI, API signature tests, and so on.
Attendees should know what tests are and that tests are an important and useful part of software development. The presentation demonstrates practical usage of a test framework. You learn techniques, tips, and tricks for testing various aspects of real-world Java™ Platform, Standard Edition (Java SE) applications. The session also gives examples of the savings and improvements that were achieved by increased usage of extensive automatic testing in the development of the NetBeans™ IDE and platform.
Posted by xzajo ( May 11 2006, 06:42:57 PM CEST ) Permalink Comments [6]First Experience with EasyMock
I like test driven development. But I don't write tests for all features of my code because it is difficult to setup testing environment. For example it is difficult to set up unit test environment for NetBeans Java Model (API). There are too many dependencies. It is possible to run tests in running NetBeans (IDE mode). But I don't prefer this variant because it takes a lot of execution time. Therefore I didn't write tests for pieces code which uses JMI API.
I found regression in my code which work quite long time. So I designed to create Mock objects for few JMI interfaces. Mock objects is implementation of classes for testing purpose. Simply you write tests against API without its implementation, It's mean that you define a scenario of use case of API's pieces in your test. For example you want to to develop tests for application which uses jdbc connection to access data. To setup database is quite difficult. So you write tests without database. You need to simulate jdbc. In this case you can use already implemented mock objects for jdbc api. Developing JDBC applications test-first is nice article about mocking jdbc. Writing of test is simple when jmock library already exists for the API. But in many cases there is no jmock implementation for API which you are using and the api is not well designed for testing. But you want to write tests at least for the critical code. You will have to write jmock objects yourself. Fortunately you can use library for writing jmock object. I know two libraries for Java languages for this purpose:
I tried to use JMock library in the past. You can mock interface and classes. I don't like two things on JMock. JMock uses strings for mocked method names. I have bad memory and I am alredy got a customed to use code completion. The jmock was dessigned for junit 3.8. The recomended way how to use jmock is to use jmock's class like supperclass for yor test case. You don't need to extends your testcase but the code is not then so nice. Today I used Easy Mock it the first time. It is dessigned for TestNG and JUnit 4. It supports jdk 1.5. You can use static import if you don't want to write the classname in everytime. You can use code completion when you define the behavior of mocked code.
I describe my first unittest for code with JMI usage. Look at the code. The comments is bellow.
import java.util.*;
import junit.framework.*;
import org.netbeans.jmi.javamodel.Method;
import org.netbeans.junit.*;
import static org.easymock.EasyMock.*;
public class ElementTest extends NbTestCase {
....
public void testParseUnknownTag() {
Method m = createMock(Method.class);
expect(m.getJavadocText()).andReturn("@myTag");
expect(m.getAnnotations()).andReturn(Collections.EMPTY_LIST);
replay(m);
Element el = Element.findElement(m);
assertNotNull(el);
Tag tag = el.getTag("myTag");
assertNotNull(tag);
assertTrue(tag.getTagTemplate().isUnknown());
assertTrue(m instanceof Method);
}
...
}
In the code is tested parsing javadoc tags from Method element. The test is separed into three parts. In the first part is created jmock object for method element. The method contains javadoc with value "/**@myTag*/" and no annotations. No more methods is used in tested code so it is not necessary to have more mocking methods. The second part activates the mock object by invoking replay(m) method. The code is tested in the last part.
By EasyMock you can also check count of calls. Let's show example. A method's call is expensive. To be sure that the method is called only one time you can write mock object for the class of method. In the test will be tested if the method is called only one time.
Posted by xzajo ( May 01 2006, 05:38:51 PM CEST ) Permalink Comments [4]