Pencarian

Rss Posts

 

 

 

JSR 292 Goodness: Fast code coverage tool in less than 10k

Feb 12, 2011

JSR 292 introduces a new bytecode instruction invokedynamic but also several new kind of constant pool constants. Which means that most of the tools that parse bytecodes like ASM, BCEL, findbugs or EMMA will need to be updated to be java 7 compatible.
EMMA is a code coverage tool, a tool that helps developers to know if their tests cover all the code of the application. While it’s not the only code coverage tool available in Java, it’s the most popular from my personal experience.
In this blog entry, I would like to show how to write a simple code coverage tool indycov that use JSR 292 API to have a runtime overhead close to zero.

How a code coverage tool works ?

A code coverage tool records all paths taken when running the application and checks at the end if all lines of codes was recorded.
By example, if I run the code below with no argument, it will print "foo" and "bar" and the code coverage tool will say that the else branch that prints "baz" will be not covered.

public static void main(String[] args) {
    System.out.println("foo");
    if (args.length == 0) {
      System.out.println("bar");
    } else {
      System.out.println("baz");
    }
  }

To record if an instruction was executed or not, code coverage tools add a probe which is a small amount of bytecodes that will call the runtime of the tool to say: "I have visited this instruction".
In fact, tools, only add probes where necessary, at the begining of each basic block of the control flow. A basic block is a collection of instructions without any jump (return, thow, if, break etc).
By example, the code above has 4 basic blocks: the once printing "foo", the one printing "bar", the one printing "baz" and the one containing the return at the end of the method.

So a code coverge tool is a tool that find basic blocks and add probes at the begining of each one.

Using JSR 292 API to implement a code coverage tool.

Finding basic block is easy with bytecode that come from 1.6 or 1.7 compiler because the compiler is required to add stack maps
in the bytecode flow. Stack maps are used to verify the bytecode in linear time and are inserted at the join points of the control flow.
So finding basic block in a 1.7 compatible bytecode can be done in one pass thanks to the stack maps info inserted by the compiler.

All existing code coverage tools have an impact on the performance of the application because the code of the probe is executed each time you call a basic block even if it should be executed once.
If you are a regular reader of this blog, you already know how to create a probe that will be executed once. The trick is use use invokedynamic, to record the visit in the bootstrap method and
to use a target method handle that is equivalent to no-op. So subsequent call will not execute any code.

main([Ljava/lang/String;)V
    INVOKEDYNAMIC probe ()V [fr/umlv/indycov/RT#bsm, 1]
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "foo"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
    ALOAD 0
    ARRAYLENGTH
    IFNE L0
    INVOKEDYNAMIC probe ()V [fr/umlv/indycov/RT#bsm, 2]
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "bar"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
    GOTO L1
    L0
    FRAME SAME
    INVOKEDYNAMIC probe ()V [fr/umlv/indycov/RT#bsm, 3]
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "baz"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
    L1
    FRAME SAME
    INVOKEDYNAMIC probe ()V [fr/umlv/indycov/RT#bsm, 4]
    RETURN

A no-op, is a method handle that takes nothing and return void. This method handle can be retrieved with Methodhandles.identity(void.class).
So the bootstrap method is the following. The first line records that the basic block with number ‘index’ is visited.

  public static CallSite bsm(Lookup lookup, String name, MethodType type, Object index) {
    classValue.get(lookup.lookupClass()).cover((Integer)index);
    return new ConstantCallSite(MethodHandles.identity(void.class));
  }

The code of the prototype is freely available (as attachment of this blog)  and works like an agent.
It relies on ASM 4 (still in beta) to do the bytecode transformation.

Side note: This prototype doesn’t handle exception correctly. If an exception is thrown, it will escape from the basic block without ending it.
How to modify the prototype to take care of exception is let to interrested readers.

Running the code with one argument "foo"

  java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -javaagent:lib/indycov.jar -cp test-classes/ TestCoverage foo

will print

  foo
  baz
  TestCoverage: no coverage for line(s) 2 to 2
  TestCoverage: no coverage for line(s) 5 to 6

line 2 is the declaration of the class, it’s because javac adds a default constructor which is not used.
lines 5 to 6 are the ones that print "bar".

If you want to play with it don’t forget to compile your sources with the debug flag on. Otherwise, the generated bytecodes will not contain mapping information between opcodes and line numbers.

Cheers,
Rémi

Attachment Size
indycov.zip 681.84 KB

Should You Close Your PHP Code Tags? – SitePoint ? PHP

Sep 17, 2010

Even those with a modest grasp of PHP know that code must be enclosed within special <?php and ?> tags.

note: Alternative PHP tags

You may also be aware that PHP code can be delimited with the lesser-used <script language=”php”> and </script> tags.

If short_open_tag is enabled within php.ini, you can use <? and ?> although they should be avoided if you?re embedding code within Xhtml or XML.

Finally, you can use the ASP-style <% and %> tags if asp_tags is set within php.ini.

However, if your file contains just PHP ? and no escaped html code ? the closing ?> tag is entirely optional. Many developers argue that unnecessary code should be removed but there?s another reason you could consider scrapping the closing tag.

Assume we have a PHP function library named library.php:


<?php
// library functions

function DoStuff() {
	// code
}
?>

The library?s included inside our main entry file, index.php:


<?php
include('library.php');

// write a header
header('X-Demo: Example');

// set cookie
setcookie('TestCookie', 'Example');
?>

<p>End of index.php file.</p>

Unfortunately, 2 warnings with the same message appear when this page is loaded:

Warning: Cannot modify header information - headers already sent

Or worse, if you could be running in a live environment where warnings have been disabled and no message appears. In either case, neither the header or the cookie is set and that could cause critical application problems.

What?s causing the error? You can?t see it, but there?s a space character following the closing ?> in the library.php file. When it?s included at the top of index.php, that space is sent as page content to the browser ? along with all the necessary HTTP headers. Once the first block of content has been sent, it?s not possible to set additional headers or cookies.

note: PHP output buffering

Modern versions of PHP set the output_buffering flag in php.ini. This buffers your html output and sends it when your PHP code has been processed or once the buffer reaches a limit (e.g. 4,096 bytes). You can also use PHP?s ob_start() and ob_end_flush() to implement your own buffering functionality.

If output buffering is enabled, you can set HTTP headers and cookies after outputting html because returned code is not sent to the browser immediately.

Note that older versions of PHP and some ISPs do not enable output buffering ? it hits server performance and requires more memory. Even if you?re certain buffering is always enabled, it?s good practice to set HTTP headers and cookies before sending page content.

Your PHP application could include dozens of library or class files. As you can imagine, it can be difficult to hunt down additional spaces, carriage returns, or any other characters following a closing ?>.

Fortunately, there?s an easy fix. If you omit the closing ?> in all your PHP-only code files, the error simply can?t occur ? the parser will ignore whitespace.

It?s a solution, but would you use it? It makes me feel a little dirty?

Do you already omit the closing ?> tag? Would you adopt the practice? Or does it just feel wrong?






Ketan Padegaonkar: Code Complexity Visualization for Ruby

Jul 21, 2010

Only Valid Measure of Code Quality

Only Valid Measure of Code Quality

Image from http://www.osnews.com/story/19266/WTFs_m

WTF implies lack of clarity. Clear code is easier to understand, easier to maintain and easier to extend.

Announcing saikuro_treemap ? an easy to setup tool to generate complexity treemaps of ruby code.

See a demo for yourself.

Complexity Visualization of Rake

RSpec Subjects Video – Teach Me To Code

May 05, 2010

Here’s a a href=”http://teachmetocode.com/screencasts/rspec-subjects”video/a on a terrific feature of a href=”/search/rspec” class=”internal”RSpec/a that allows you to write concise and readable tests.div class=”feedflare”
a href=”http://feeds.feedburner.com/~ff/Rubyflow?a=4922dEbFeug:tu5H_pxpOAQ:3H-1DwQop_U”img src=”http://feeds.feedburner.com/~ff/Rubyflow?i=4922dEbFeug:tu5H_pxpOAQ:3H-1DwQop_U” border=”0″/img/a
/divimg src=”http://feeds.feedburner.com/~r/Rubyflow/~4/4922dEbFeug” height=”1″ width=”1″/

Testing: Making Sure Code Works Before Shipping It – Brandon Savage

Jan 13, 2010

Shipping code that works is crucial to retaining the support of customers and high quality in your application. While it?s impossible to ship code without any bugs at all, it is possible to control for as many as possible, and fix as many known issues as there is time. These strategies are designed to ensure that code works when it is shipped to the end user.

Employ testers.
Developers have a tendency to test their code only with expected data. Testers, on the other hand, aren?t developers themselves; instead, they will use data that you don?t expect and find bugs that your users might otherwise experience.

Hiring testers is a tough sell in many development teams, especially small ones. It is possible to have testers that have other functions ? that is, they might be in another department or moonlight as testers. But with teams larger than 5 developers, having a full time tester is a crucial component of good development practices.

Write unit tests.
Every developer makes mistakes at some point. Having unit tests in place will help find these mistakes by showing you where a class breaks. It makes refactoring easier as well, since you can refactor and know that if your unit tests pass, there?s a good chance that you did it properly.

Unit testing should be built into the process of code development from the beginning of a project. However, if you?re starting from someone else?s project and the project doesn?t have unit tests already, simply institute a process of fixing bugs after you?ve written a unit test that identifies the bug. Eventually you?ll have unit tests for most of the application.

Write functional tests.
Unit tests are great, but they?re not enough. Knowing that one function takes an array and creates an object is fine, but what happens with the next function, and the one after that? Introducing functional tests: testing against expected behavior.

There?s a subtle difference between these two concepts. Unit tests test a specific component of the code: a single method, function, or clause. Functional testing, on the other hand, tests expected behavior: does clicking that button actually result in a refreshed page? Does my controller actually invoke the action properly? More than one method might be acted upon with functional testing.

A lot of this testing is done by the testers; however with applications like Selenium you can conduct some automated functional tests. On a small team that doesn?t have testers, or on a large team where there might be a challenged set of resources, automated functional tests can help reduce the testing burden.

Work unit testing into your build process.
We talked about integrating your build process with a continuous integration server. With build engines like Phing, it?s possible to automate the unit testing process (and even the functional testing process to some degree).

Each time you make a build for release, you should know that all the unit tests pass. If they don?t, there?s a problem that should be addressed before the build is completed.

Use continuous integration to know when tests began failing.
To hit on the same theme, a solid continuous integration server will automatically run your tests and alert you as soon as the first one fails. This helps prevent regression ? the introduction of bugs into code that worked in previous releases. The time to discover regression isn?t when the build is due and the team is ready to go, it?s right after a commit, and continuous integration will help with this.