Menu

not all classes instrumented.big bug???

2004-09-12
2004-09-12
  • Dean Hiller

    Dean Hiller - 2004-09-12

    I am working on an open source project and when I instrument the jar or the build folder, emma is missing some classes in the instrumented directory so when the tests run, I get NoClassDefError.  I am using instrumentation, then junit, then reporting.  It doesn't seem to work.  Is anyone else having this problem?  This seems like a major problem as my junit does not even pass so I get no code coverage.  I am happy to either give you the xml code or give you a reference to my project where build.sh or build.bat can be run.
    thanks,
    dean

     
    • Dean Hiller

      Dean Hiller - 2004-09-12

      ohhh, duh, I thought about this a little more.  The interfaces can't be instrumented, so I actually need to copy all class files over to the instrumentation directory from the classes directory, and then instrument from classes directory to the instrumentation directory overwriting the class files.  Otherwise, I guess I could have instrumentation directory ahead on the classpath, but it seems like a hack.  IT would be very very nice if instrumentation copied over the interfaces as well as instrumenting the classes so one could just define the classpath as the instrumentation directory plus third party libs.
      thanks,
      dean

       
    • Nobody/Anonymous

      interesting.  can't do that either.  If the classes are copied over the instrumenter decides not to instrument.  I finally got it though by just putting the instrumentation directory ahead of the classes directory on the classpath.  I am a little nervous about this as one change to ant, and the order on the classpath could be reversed leaving me hanging again.  seems like a bad dependency to have when I just want to specify to use the instrumentation directory for all the class/interface files.  oh well, works for now I guess.

       
    • Vlad Roubtsov

      Vlad Roubtsov - 2004-09-12

      >I finally got it though by just putting the instrumentation directory ahead of the classes directory on the classpath.

      (1) This in fact is the recommended (and documented) way to use the default "copy" mode of <instr>.

      The motivation behind "copy" mode has been to do as little file I/O as possible and thus keep personal development fast and iterative. File I/O is the current performance bottleneck. If I want to coverage-profile one package in a large project with 2000+ classes, I don't want to wait for <instr> to copy 2000+ file, most of which it doesn't even instrument.

      I recommend going through build-offline.xml and build-onthefly.xml examples that ship with EMMA. Specifically, they show how I recommend dealing with these issues. For example, in build-offline.xml I use a classpath dir that's set from a property that is only defined if emma task is used on ANT's command line:

        <target name="emma" description="turns on EMMA's instrumentation/reporting" >
          <property name="emma.enabled" value="true" />
          <!-- EMMA instr class output directory (it is important to create
               this property only when EMMA is enabled:
          -->
          <property name="out.instr.dir" value="${basedir}/outinstr" />
          <mkdir dir="${out.instr.dir}" />
         
          <!-- this property, if overriden via -Demma.filter=<list of filter specs>
               on ANT's command line, will set the coverage filter; by default,
               all classes found in 'run.classpath' pathref will be instrumented:
          -->
          <property name="emma.filter" value="" />
        </target>

      ...

      <java classname="Main" fork="true" >
            <classpath>
              <!-- instrumented classes must be first in the classpath: -->
              <pathelement location="${out.instr.dir}" />
              <path refid="run.classpath" />
              <!-- the forked JVM must have emma.jar in the classpath: -->
              <path refid="emma.lib" />
            </classpath>
            <!-- to be certain, tell EMMA runtime where to dump the runtime
                 coverage data (otherwise the filename is relative to the JVM's
                 current directory and it is easy to get confused about what
                 that is):
            -->
            <jvmarg value="-Demma.coverage.out.file=${coverage.dir}/coverage.emma" />
            <jvmarg value="-Demma.coverage.out.merge=false" />
          </java>

      Thus, doing "ant emma all" turns coverage on and ensures that the instr class dir is the first one in the overall classpath. Doing "ant all" runs things without any EMMA intervention.

      This is a bit of an ANT hack but I needed to show to do this in ANT 1.4. I am sure you can do this even more elegantly in later ANT versions.

      (2) I admit I don't understand why you think copying over doesn't work. All you need to do is a sequence of two steps:

      - do instr.
      - copy over all instr-output classes into whatever your application classpath location should be. The instrumented classes replace the their uninstrumented versions and everything is magically as it should be.
      - use this "merged" classpath at runtime. Use the original classpath when coverage is not needed.

      What am I missing?

      (3) And finally, if you do want to use  EMMA as a file copy tool, switch instr to "fullcopy" mode. In this mode, *all* content is copied to the output location, whether it is instrumented or not (and whether it is even .class content or not).

      Details on "fullcopy" could be found in EMMA docs.'

      The way the default "copy" mode works seems to have caused enough misunderstanding to make me doubt my original design intentions for it. Of course, I only hear from people who have problem and not from those who read the docs and made the right choice for their build designs. If you think I need to change EMMA behavior in future versions, let me know.

       
    • Dean Hiller

      Dean Hiller - 2004-09-12

      I did get it all working.  Check out my other post and try out that buildtemplate.  It is kind of just a toy I am playing with.

      duuh, I forgot I could have done it that way(ie. the copy you mention).  I first copied to ${instr} and then instrumented to that same directory.  I guess I could have instrumented first and then copied both ${classes} and ${instr} into another directory....I didn't want to corrupt ${classes} as that is what the jar is built from and I obviously don't want a instrumented jar shipped.

      thanks,
      dean

       

Log in to post a comment.