[fyi] [icedtea-web] new code coverage direction - jacoco

Adam Domurad adomurad at redhat.com
Tue Dec 11 10:00:33 PST 2012


Comments inline

On 12/11/2012 12:04 PM, Jiri Vanek wrote:
>   [ .. snip .. ]
>>
>> So I take it that this patch relies on a few components that are not 
>> yet upstream ? What is the
>> current effect of the patch ?
>
> Luckily, my packaging patch was already pushed to testing and looks good-
> https://admin.fedoraproject.org/updates/FEDORA-2012-20019/jacoco-0.5.9-3.fc17 
> (and one for f18 and rawhide).

Cool :)

>
> There rise (past tense:) small complication - in f17 jacoco will 
> remain compatible with asm3, in 18+ with asm4. (see the change in 
> configure.ac)
>
> So now, with this updated jacoco installed, asm3 as default (on f17 
> and asm4 on f18+) and my patch in, you will run successfully unittest 
> coverage.
>
> My patch for upstream to allow coverage of bootclassapth is still in 
> progress of upstreaming so to run reproducers coverage you must have 
> your custom jacoco build:(
>
> Report generation tool will be in icedtea-web repository untill it is 
> upstreamed. so there is no harm by this not being upstreamed yet.
>
> One more hint - asm3 is causing that report is not generated. So you 
> need custom asm4 jacoco anyway.... I will discuse with jacoco 
> maintainer this issue one more times.

Thanks for the details.

>
>
>>
>>> diff -r aff6fb36a9ab Makefile.am
>>> --- a/Makefile.am    Mon Dec 03 18:08:38 2012 +0100
>>> +++ b/Makefile.am    Wed Dec 05 16:40:30 2012 +0100
>>> @@ -20,6 +20,8 @@
>>>   export JUNIT_RUNNER_DIR=$(TESTS_DIR)/junit-runner
>>>   export JUNIT_RUNNER_SRCDIR=$(TESTS_SRCDIR)/junit-runner
>>>
>>> +export JACOCO_OPERATOR_DIR=$(TESTS_DIR)/jacoco-operator
>>> +export JACOCO_OPERATOR_SRCDIR=$(TESTS_SRCDIR)/jacoco-operator
>>>
>>>   export TEST_EXTENSIONS_SRCDIR=$(TESTS_SRCDIR)/test-extensions
>>>   export 
>>> TEST_EXTENSIONS_TESTS_SRCDIR=$(TESTS_SRCDIR)/test-extensions-tests
>>> @@ -56,6 +58,22 @@
>>>   export ALL_NONCUSTOM_REPRODUCERS=$(SIMPLE_REPRODUCERS) 
>>> $(SIGNED_REPRODUCERS)
>>>   export ALL_REPRODUCERS=$(ALL_NONCUSTOM_REPRODUCERS) 
>>> $(CUSTOM_REPRODUCERS)
>>>
>>> +export JACOCO_PATH:=$(shell dirname "$(JACOCO_JAR)")
>>> +export JACOCO_AGENT=org.jacoco.agent.jar
>>> +export JACOCO_ANT=org.jacoco.ant.jar
>>> +export JACOCO_REPORT=org.jacoco.report.jar
>>> +export JACOCO_AGENTRT=org.jacoco.agent.rt.jar
>>> +export JACOCO_CORE=org.jacoco.core.jar
>>> +export JACOCO_JAVAWS_RESULTS=$(TEST_EXTENSIONS_DIR)/jacoco_javaws.exec
>>> +export JACOCO_PLUGIN_RESULTS=$(TEST_EXTENSIONS_DIR)/jacoco_plugin.exec
>>> +export 
>>> JACOCO_CLASSPATH=$(JACOCO_PATH)/$(JACOCO_CORE):$(JACOCO_PATH)/$(JACOCO_AGENT):$(JACOCO_PATH)/$(JACOCO_REPORT):$(JACOCO_PATH)/$(JACOCO_AGENTRT):$(JACOCO_PATH)/$(JACOCO_ANT):$(ASM4_JAR)
>>> +export 
>>> JACOCO_AGENT_SWITCH_BODY=-javaagent:$(JACOCO_PATH)/$(JACOCO_AGENTRT)
>>> +export JACOCO_BASE_EXCLUDE=org.junit.*:junit.*
>>> +export 
>>> JACOCO_ADVANCED_EXCLUDE=:*jacoco*:java.lang.*:java.reflect.*:java.util.*:sun.reflect.*
>>> +export 
>>> JACOCO_AGENT_SWITCH="$(JACOCO_AGENT_SWITCH_BODY)=excludes=$(JACOCO_BASE_EXCLUDE)"
>>> +export 
>>> JACOCO_AGENT_JAVAWS_SWITCH=\"$(JACOCO_AGENT_SWITCH_BODY)=excludes=$(JACOCO_BASE_EXCLUDE)$(JACOCO_ADVANCED_EXCLUDE),xboot=true,destfile=$(JACOCO_JAVAWS_RESULTS)\"
>>> +export 
>>> JACOCO_AGENT_PLUGIN_SWITCH=\"$(JACOCO_AGENT_SWITCH_BODY)=excludes=$(JACOCO_BASE_EXCLUDE)$(JACOCO_ADVANCED_EXCLUDE),xboot=true,destfile=$(JACOCO_PLUGIN_RESULTS)\"
>>> +export JACOCO_OPERATOR_EXEC=$(BOOT_DIR)/bin/java $(EMMA_JAVA_ARGS) 
>>> -cp $(JACOCO_OPERATOR_DIR):$(JACOCO_CLASSPATH):. 
>>> org.jacoco.operator.Main
>>>
>>>   # linking variables
>>>   export PLUGIN_LINK_NAME=libjavaplugin.so
>>> @@ -103,6 +121,7 @@
>>>   #
>>>   export 
>>> LAUNCHER_BOOTCLASSPATH="-Xbootclasspath/a:$(datadir)/$(PACKAGE_NAME)/netx.jar$(RHINO_RUNTIME)"
>>>   export 
>>> PLUGIN_BOOTCLASSPATH='"-Xbootclasspath/a:$(datadir)/$(PACKAGE_NAME)/netx.jar:$(datadir)/$(PACKAGE_NAME)/plugin.jar$(RHINO_RUNTIME)"'
>>> +export 
>>> PLUGIN_COVERAGE_BOOTCLASSPATH='"-Xbootclasspath/a:$(datadir)/$(PACKAGE_NAME)/netx.jar:$(datadir)/$(PACKAGE_NAME)/plugin.jar$(RHINO_RUNTIME):$(JACOCO_CLASSPATH)"'
>>>
>>>   # Fake update version to work with the Deployment Toolkit script 
>>> used by Oracle
>>> #http://download.oracle.com/javase/tutorial/deployment/deploymentInDepth/depltoolkit_index.html
>>> @@ -128,6 +147,9 @@
>>>   export LIVECONNECT_SRCS = $(PLUGIN_SRCDIR)/java
>>>   export ICEDTEAPLUGIN_TARGET = 
>>> $(PLUGIN_DIR)/$(BUILT_PLUGIN_LIBRARY) stamps/liveconnect-dist.stamp
>>>   export PLUGIN_PKGS = sun.applet netscape.security netscape.javascript
>>> +#those are for plugin testcoverage
>>> +export FAKE_PLUGIN_SRCDIR=$(TESTS_DIR)/icedteanp-srcs
>>> +export FAKE_PLUGIN_DIR=$(TESTS_DIR)/icedteanp-build
>>
>> FAKE_PLUGIN is confusing, it sounds to me a bit like a 'phony 
>> target'. Maybe INSTRUMENTED_PLUGIN...
>> (or something less verbose if you choose)
>
> become COVERABLE_PLUGIN
>>
>>>   endif
>>>
>>>   if CP_SUPPORTS_REFLINK
>>> @@ -588,6 +610,9 @@
>>>   junit-runner-source-files.txt:
>>>       find $(JUNIT_RUNNER_SRCDIR) -name '*.java' | sort > $@
>>>
>>> +jacoco-operator-source-files.txt:
>>> +    find $(JACOCO_OPERATOR_SRCDIR) -name '*.java' | sort > $@
>>> +
>>>   $(JUNIT_RUNNER_JAR): junit-runner-source-files.txt 
>>> stamps/test-extensions-compile.stamp
>>>       mkdir -p $(JUNIT_RUNNER_DIR) && \
>>>       $(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
>>> @@ -825,8 +850,8 @@
>>>         $(BOOT_DIR)/bin/java $(REPRODUCERS_DPARAMETERS) \
>>>        -Xbootclasspath:$(RUNTIME) CommandLine $$class_names
>>>   if WITH_XSLTPROC
>>> -    $(XSLTPROC)  --stringparam logs logs_reproducers.html 
>>> $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/jreport.xsl 
>>> $(TEST_EXTENSIONS_DIR)/tests-output.xml > 
>>> $(TESTS_DIR)/index_reproducers.html
>>> -    $(XSLTPROC) $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/logs.xsl 
>>> $(TEST_EXTENSIONS_DIR)/ServerAccess-logs.xml > 
>>> $(TESTS_DIR)/logs_reproducers.html
>>> +    -$(XSLTPROC)  --stringparam logs logs_reproducers.html 
>>> $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/jreport.xsl 
>>> $(TEST_EXTENSIONS_DIR)/tests-output.xml > 
>>> $(TESTS_DIR)/index_reproducers.html
>>> +    -$(XSLTPROC) $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/logs.xsl 
>>> $(TEST_EXTENSIONS_DIR)/ServerAccess-logs.xml > 
>>> $(TESTS_DIR)/logs_reproducers.html
>>>   endif
>>>       touch $@
>>>
>>> @@ -1002,8 +1027,8 @@
>>> CLASSPATH=$(NETX_DIR)/lib/classes.jar:$(JUNIT_JAR):$(JUNIT_RUNNER_JAR):$(TEST_EXTENSIONS_DIR):. 
>>> \
>>>         $(BOOT_DIR)/bin/java -Xbootclasspath:$(RUNTIME) CommandLine 
>>> $$class_names
>>>   if WITH_XSLTPROC
>>> -    $(XSLTPROC) --stringparam logs logs_unit.html 
>>> $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/jreport.xsl 
>>> $(NETX_UNIT_TEST_DIR)/tests-output.xml > $(TESTS_DIR)/index_unit.html
>>> -    $(XSLTPROC) $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/logs.xsl 
>>> $(NETX_UNIT_TEST_DIR)/ServerAccess-logs.xml > 
>>> $(TESTS_DIR)/logs_unit.html
>>> +    -$(XSLTPROC) --stringparam logs logs_unit.html 
>>> $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/jreport.xsl 
>>> $(NETX_UNIT_TEST_DIR)/tests-output.xml > $(TESTS_DIR)/index_unit.html
>>> +    -$(XSLTPROC) $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/logs.xsl 
>>> $(NETX_UNIT_TEST_DIR)/ServerAccess-logs.xml > 
>>> $(TESTS_DIR)/logs_unit.html
>>>   endif
>>>       mkdir -p stamps && \
>>>       touch $@
>>> @@ -1049,6 +1074,53 @@
>>>   endif
>>>       touch $@
>>>
>>> +stamps/compile-jacoco-operator.stamp: jacoco-operator-source-files.txt
>>> +if WITH_JACOCO
>>> +    mkdir -p $(JACOCO_OPERATOR_DIR) && \
>>> +    $(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
>>> +      -d $(JACOCO_OPERATOR_DIR) \
>>> +      -classpath $(JACOCO_CLASSPATH) \
>>> +      @jacoco-operator-source-files.txt ;
>>> +else
>>> +    echo "Sorry, jacoco coverage report generator  cant be compiled 
>>> without jacoco installed. Try install jacoco or specify with-jacoco 
>>> value" ;
>>>
>>
>> Do you mean 'Try installing jacoco'  ? It sounds like you're 
>> suggesting a command :)
>
> fixed!
>
>>
>>
>>> +    exit 5
>>> +endif
>>> +    touch $@
>>> +
>>> +
>>> +#warning,  during this target 
>>> tests.build/netx/unit/tests-output.xml is backup and rewriten (but 
>>> not coresponding html file)
>>> +#xml results run with jacoco agent however, can be wrong, co the 
>>> new tests-output.xml is then renamed and orginal one restored
>>> +stamps/run-unit-test-code-coverage-jacoco.stamp: 
>>> stamps/netx-unit-tests-compile.stamp $(JUNIT_RUNNER_JAR)  \
>>> + $(TESTS_DIR)/$(REPORT_STYLES_DIRNAME)  $(UNIT_CLASS_NAMES) 
>>> stamps/compile-jacoco-operator.stamp
>>> +if WITH_JACOCO
>>> +    filename=" " ; \
>>> +    cd $(NETX_UNIT_TEST_SRCDIR) ; \
>>> +    for file in `find . -type f \! -iname "*.java"`; do\
>>> +        filename=`echo $$file `; \
>>> +        cp --parents $$filename $(NETX_UNIT_TEST_DIR) ; \
>>> +    done ; \
>>> +    cd $(NETX_UNIT_TEST_DIR) ; \
>>> +    for file in $(EMMA_MODIFIED_FILES) ; do \
>>> +      mv $(NETX_UNIT_TEST_DIR)/$$file 
>>> $(NETX_UNIT_TEST_DIR)/"$$file""$(EMMA_BACKUP_SUFFIX)" ; \
>>> +    done ;\
>>> +    class_names=`cat $(UNIT_CLASS_NAMES)` ; \
>>> + 
>>> CLASSPATH=$(NETX_DIR)/lib/classes.jar:$(JUNIT_JAR):$(JUNIT_RUNNER_JAR):$(TEST_EXTENSIONS_DIR):$(JACOCO_CLASSPATH):. 
>>> \
>>> +      $(BOOT_DIR)/bin/java $(JACOCO_AGENT_SWITCH) 
>>> -Xbootclasspath:$(RUNTIME)  CommandLine $$class_names ; \
>>> +    for file in $(EMMA_MODIFIED_FILES) ; do \
>>> +      mv $(NETX_UNIT_TEST_DIR)/$$file 
>>> $(NETX_UNIT_TEST_DIR)/"$$file""$(EMMA_SUFFIX)" ; \
>>> +      mv $(NETX_UNIT_TEST_DIR)/"$$file""$(EMMA_BACKUP_SUFFIX)" 
>>> $(NETX_UNIT_TEST_DIR)/$$file ; \
>>> +    done ; \
>>> +    $(JACOCO_OPERATOR_EXEC) \
>>> +      report --die-soon --html-output coverage --xml-output 
>>> coverage.xml --input-file jacoco.exec \
>>> +      --input-srcs  $(NETX_SRCDIR) $(PLUGIN_SRCDIR)/java 
>>> $(NETX_UNIT_TEST_SRCDIR) $(JUNIT_RUNNER_SRCDIR) 
>>> $(TEST_EXTENSIONS_SRCDIR) \
>>> +      --input-builds $(NETX_DIR)/lib/classes.jar 
>>> $(abs_top_builddir)/liveconnect/lib/classes.jar 
>>> $(NETX_UNIT_TEST_DIR) $(JUNIT_RUNNER_JAR) $(TEST_EXTENSIONS_DIR) \
>>> +      --title "IcedTea-Web unit-tests codecoverage" ;
>>> +else
>>> +    echo "Sorry, coverage report cant be run without jacoco 
>>> installed. Try install jacoco or specify with-jacoco value" ;
>>
>> See above
>>
>>> +    exit 5
>>> +endif
>>> +    touch $@
>>> +
>>>   #warning,  during this target 
>>> tests.build/netx/jnlp_testsengine/tests-output.xml is backup and 
>>> rewriten (but not coresponding html file)
>>>   #xml results run from emma sandbox, however, can be wrong, co the 
>>> new tests-output.xml is then renamed and orginal one restored
>>>   stamps/run-reproducers-test-code-coverage.stamp: 
>>> stamps/run-netx-dist-tests.stamp $(REPRODUCERS_CLASS_NAMES)
>>> @@ -1139,7 +1211,152 @@
>>>   endif
>>>       touch $@
>>>
>>> -run-test-code-coverage: run-unit-test-code-coverage 
>>> run-reproducers-test-code-coverage
>>> +$(FAKE_PLUGIN_SRCDIR):
>>> +    mkdir -p $(FAKE_PLUGIN_SRCDIR) ; \
>>> +    cp -r $(PLUGIN_SRCDIR)/* $(FAKE_PLUGIN_SRCDIR) ; \
>>> +    cd $(FAKE_PLUGIN_SRCDIR) ; \
>>> +    rm *.o ; \
>>> +    rm *.so ; \
>>> +    rm -rf java ; \
>>> +    patch -p0 < $(TESTS_SRCDIR)/plugin_fakeing.patch ; \
>>> +    mkdir -p $(FAKE_PLUGIN_DIR);
>>
>> I don't know if I like this approach, a patch is pretty brittle and 
>> easy to break by accident (it
>> already happened). See my comments below near the patch file for 
>> suggestions of alternatives (which
>> doesn't involve copying and patching source).
>
> Sure. With list this is getting much more simple.
>
>>
>>> +
>>> +$(FAKE_PLUGIN_DIR)/%.o: $(FAKE_PLUGIN_SRCDIR)/%.cc
>>> +    cd $(FAKE_PLUGIN_DIR) && \
>>> +    $(CXX) $(CXXFLAGS) \
>>> +       $(DEFS) $(VERSION_DEFS) \
>>> +      -DJDK_UPDATE_VERSION="\"$(JDK_UPDATE_VERSION)\"" \
>>> +      -DPLUGIN_NAME="\"IcedTea-Web Faked Plugin\"" \
>>
>> 'IcedTea-Web Plugin with Jacoco' will be clearer if anyone happens to 
>> see this message.
>>
>>> + -DPLUGIN_VERSION="\"$(PLUGIN_VERSION)\"" \
>>> +      -DPACKAGE_URL="\"$(PACKAGE_URL)\"" \
>>> + -DMOZILLA_VERSION_COLLAPSED="$(MOZILLA_VERSION_COLLAPSED)" \
>>> +      -DICEDTEA_WEB_JRE="\"$(SYSTEM_JRE_DIR)\"" \
>>> +      -DPLUGIN_BOOTCLASSPATH=$(PLUGIN_COVERAGE_BOOTCLASSPATH) \
>>> +      -DCOVERAGE_AGENT=$(JACOCO_AGENT_PLUGIN_SWITCH) \
>>> +      $(GLIB_CFLAGS) \
>>> +      $(GTK_CFLAGS) \
>>> +      $(MOZILLA_CFLAGS) \
>>> +      -fvisibility=hidden \
>>> +      -fPIC -o $@ -c $<
>>> +
>>> +$(FAKE_PLUGIN_DIR)/$(BUILT_PLUGIN_LIBRARY): $(addprefix 
>>> $(FAKE_PLUGIN_DIR)/,$(PLUGIN_OBJECTS))
>>> +    cd $(FAKE_PLUGIN_DIR) && \
>>> +    $(CXX) $(CXXFLAGS) \
>>> +      $(PLUGIN_OBJECTS) \
>>> +      $(GLIB_LIBS) \
>>> +      $(GTK_LIBS) \
>>> +      $(MOZILLA_LIBS) \
>>> +      -shared -o $@
>>> +
>>> +stamps/build-fake-plugin.stamp:  $(FAKE_PLUGIN_SRCDIR) $(addprefix 
>>> $(FAKE_PLUGIN_SRCDIR)/,$(PLUGIN_SRC)) $(addprefix 
>>> $(FAKE_PLUGIN_DIR)/,$(PLUGIN_OBJECTS)) stamps/liveconnect-dist.stamp 
>>> $(FAKE_PLUGIN_DIR)/$(BUILT_PLUGIN_LIBRARY)
>>> +    touch $@
>>> +
>>> +#warning,  during this target 
>>> tests.build/netx/jnlp_testsengine/tests-output.xml is backup and 
>>> rewriten (but not coresponding html file)
>>> +#xml results run with jacoco agent, however, can be wrong, co the 
>>> new tests-output.xml is then renamed and orginal one restored
>>> +stamps/run-reproducers-test-code-coverage-jacoco.stamp: 
>>> stamps/run-netx-dist-tests.stamp $(REPRODUCERS_CLASS_NAMES) \
>>> +stamps/compile-jacoco-operator.stamp stamps/build-fake-plugin.stamp
>>> +if WITH_JACOCO
>>> +    cd $(TESTS_DIR) ; \
>>> +    for file in $(EMMA_MODIFIED_FILES) ; do \
>>> +      mv $(TEST_EXTENSIONS_DIR)/$$file 
>>> $(TEST_EXTENSIONS_DIR)/"$$file""$(EMMA_BACKUP_SUFFIX)" ; \
>>> +    done ;\
>>> +    echo "backuping javaws in $(DESTDIR)$(bindir)" ; \
>>> +    javaws_backup=$(DESTDIR)$(bindir)/javaws_backup ; \
>>> +    mv $(DESTDIR)$(bindir)/javaws $$javaws_backup ;  \
>>> +    echo "patching $(javaws)" ; \
>>> + nw_bootclasspath="$(LAUNCHER_BOOTCLASSPATH):$(JACOCO_CLASSPATH)" ; \
>>> +    cat $$javaws_backup | sed 
>>> "s|COMMAND.k.=\"..JAVA.\"|COMMAND[k]=\"\\$$\\{JAVA\\}\" ;  k=1 ; 
>>> COMMAND[k]=$(JACOCO_AGENT_JAVAWS_SWITCH)|" | sed 
>>> "s,$(LAUNCHER_BOOTCLASSPATH),$$nw_bootclasspath," > 
>>> $(DESTDIR)$(bindir)/$(javaws) ; \
>>> +    chmod 777 $(DESTDIR)$(bindir)/$(javaws) ; \
>>> +    echo "backuping plugin in 
>>> $(DESTDIR)/$(libdir)$(BUILT_PLUGIN_LIBRARY)" ; \
>>> + plugin_backup=$(DESTDIR)$(libdir)/$(BUILT_PLUGIN_LIBRARY)_backup ; \
>>> +    mv $(DESTDIR)$(libdir)/$(BUILT_PLUGIN_LIBRARY) $$plugin_backup 
>>> ;  \
>>> +    echo "fakeing plugin" ; \
>>> +    cp $(FAKE_PLUGIN_DIR)/$(BUILT_PLUGIN_LIBRARY) 
>>> $(DESTDIR)$(libdir)/$(BUILT_PLUGIN_LIBRARY) ; \
>>> +    testcases_srcs=( ) ; \
>>> +    k=0 ; \
>>> +    types=($(ALL_REPRODUCERS)); \
>>> +    for which in "$${types[@]}" ; do \
>>> +      . $(abs_top_srcdir)/NEW_LINE_IFS ; \
>>> +      simpleReproducers=(`cat 
>>> $(abs_top_builddir)/junit-jnlp-dist-$$which.txt `); \
>>> +      IFS="$$IFS_BACKUP" ; \
>>> +      for dir in "$${simpleReproducers[@]}" ; do \
>>> + 
>>> testcases_srcs[k]="$(REPRODUCERS_TESTS_SRCDIR)/$$which/$$dir/testcases/" 
>>> ; \
>>> +        k=$$((k+1)) ; \
>>> +        done ; \
>>> +      done ; \
>>> +    cd $(TEST_EXTENSIONS_DIR) ; \
>>> +    class_names=`cat $(REPRODUCERS_CLASS_NAMES)` ; \
>>> + 
>>> CLASSPATH=$(NETX_DIR)/lib/classes.jar:$(JUNIT_JAR):$(JUNIT_RUNNER_JAR):.:$(TEST_EXTENSIONS_DIR):$(JACOCO_CLASSPATH):$(TEST_EXTENSIONS_TESTS_DIR) 
>>> \
>>> +      $(BOOT_DIR)/bin/java $(JACOCO_AGENT_SWITCH) 
>>> $(REPRODUCERS_DPARAMETERS) \
>>> +     -Xbootclasspath:$(RUNTIME) CommandLine $$class_names ; \
>>> +    if [ -f $(JACOCO_JAVAWS_RESULTS) ] ; then \
>>> +      jacoco_javaws_results=$(JACOCO_JAVAWS_RESULTS) ; \
>>> +      $(JACOCO_OPERATOR_EXEC) \
>>> +        report --die-soon --html-output coverage-javaws 
>>> --xml-output coverage-javaws.xml --input-file 
>>> $(JACOCO_JAVAWS_RESULTS) \
>>> +        --input-srcs  $(NETX_SRCDIR) \
>>> +        --input-builds $(NETX_DIR)/lib/classes.jar \
>>> +        --title "IcedTea-Web javaws reproducers codecoverage" ; \
>>> +    fi; \
>>> +    if [ -f $(JACOCO_PLUGIN_RESULTS) ] ; then \
>>> +      jacoco_plugin_results=$(JACOCO_PLUGIN_RESULTS) ; \
>>> +      $(JACOCO_OPERATOR_EXEC) \
>>> +        report --die-soon --html-output coverage-plugin 
>>> --xml-output coverage-plugin.xml --input-file 
>>> $(JACOCO_PLUGIN_RESULTS) \
>>> +        --input-srcs  $(NETX_SRCDIR) $(PLUGIN_SRCDIR)/java \
>>> +        --input-builds $(NETX_DIR)/lib/classes.jar 
>>> $(abs_top_builddir)/liveconnect/lib/classes.jar \
>>> +        --title "IcedTea-Web plugin reproducers codecoverage" ; \
>>> +    fi; \
>>> +    $(JACOCO_OPERATOR_EXEC) \
>>> +      merge --die-soon --input-files jacoco.exec 
>>> $$jacoco_javaws_results $$jacoco_plugin_results  --output-file 
>>> jacoco-merged-reproducers.exec ; \
>>> +    $(JACOCO_OPERATOR_EXEC) \
>>> +      report --html-output coverage --xml-output coverage.xml 
>>> --input-file jacoco-merged-reproducers.exec \
>>> +      --input-srcs  $(NETX_SRCDIR) $(PLUGIN_SRCDIR)/java 
>>> $(JUNIT_RUNNER_SRCDIR) $(TEST_EXTENSIONS_SRCDIR) 
>>> $(TEST_EXTENSIONS_TESTS_SRCDIR) "$${testcases_srcs[@]}" \
>>> +      --input-builds $(NETX_DIR)/lib/classes.jar 
>>> $(abs_top_builddir)/liveconnect/lib/classes.jar $(JUNIT_RUNNER_JAR)  
>>> $(TEST_EXTENSIONS_DIR) $(TEST_EXTENSIONS_TESTS_DIR) \
>>> +      --title "IcedTea-Web reproducers-tests codecoverage" ; \
>>> +    echo "restoring javaws in $(DESTDIR)$(bindir)" ; \
>>> +    rm -f $(DESTDIR)$(bindir)/$(javaws);  \
>>> +    mv $$javaws_backup $(DESTDIR)$(bindir)/$(javaws);  \
>>> +    echo "restoring  plugin in 
>>> $(DESTDIR)/$(libdir)$(BUILT_PLUGIN_LIBRARY)" ; \
>>> +    mv $$plugin_backup $(DESTDIR)$(libdir)/$(BUILT_PLUGIN_LIBRARY) ; \
>>> +    for file in $(EMMA_MODIFIED_FILES) ; do \
>>> +      mv $(TEST_EXTENSIONS_DIR)/$$file 
>>> $(TEST_EXTENSIONS_DIR)/"$$file""$(EMMA_SUFFIX)" ; \
>>> +      mv $(TEST_EXTENSIONS_DIR)/"$$file""$(EMMA_BACKUP_SUFFIX)" 
>>> $(TEST_EXTENSIONS_DIR)/$$file ; \
>>> +    done ;
>>> +else
>>> +    echo "Sorry, coverage report cant be run without jacoco 
>>> installed. Try install jacoco or specify with-jacoco value" ;
>>> +    exit 5
>>> +endif
>>> +    touch $@
>>
>> My eyes ... could this be its own bash script ? Maybe then I could 
>> actually read it ...
>
> no :)

You can leave this in if you really want ... but I would feel better if 
there was a bash script with utilities to make this all nicer. Per our 
discussion on IRC, a bash script with 'set -e' will exit on any error, 
making it work nicer with make.
I get what its doing, but there really is a lot of noise-to-signal going 
on here, so its hard to review in any sort of depth.

>
>>
>>> +
>>> +run-test-code-coverage-jacoco: 
>>> stamps/run-unit-test-code-coverage-jacoco.stamp 
>>> stamps/run-reproducers-test-code-coverage-jacoco.stamp
>>> +if WITH_JACOCO
>>> +    cd $(TESTS_DIR) ; \
>>> +    k=0 ; \
>>> +    types=($(ALL_REPRODUCERS)); \
>>> +    for which in "$${types[@]}" ; do \
>>> +      . $(abs_top_srcdir)/NEW_LINE_IFS ; \
>>> +      simpleReproducers=(`cat 
>>> $(abs_top_builddir)/junit-jnlp-dist-$$which.txt `); \
>>> +      IFS="$$IFS_BACKUP" ; \
>>> +      for dir in "$${simpleReproducers[@]}" ; do \
>>> + 
>>> testcases_srcs[k]="$(REPRODUCERS_TESTS_SRCDIR)/$$which/$$dir/testcases/" 
>>> ; \
>>> +        k=$$((k+1)) ; \
>>> +        done ; \
>>> +      done ; \
>>> +    class_names=`cat $(REPRODUCERS_CLASS_NAMES)` ; \
>>> +    $(JACOCO_OPERATOR_EXEC) \
>>> +      merge --die-soon --input-files 
>>> $(TEST_EXTENSIONS_DIR)/jacoco-merged-reproducers.exec 
>>> $(NETX_UNIT_TEST_DIR)/jacoco.exec  --output-file jacoco-merged.exec; \
>>> +    $(JACOCO_OPERATOR_EXEC) \
>>> +      report --html-output coverage --xml-output coverage.xml 
>>> --input-file jacoco-merged.exec \
>>> +      --input-srcs  $(NETX_SRCDIR) $(PLUGIN_SRCDIR)/java 
>>> $(JUNIT_RUNNER_SRCDIR) $(TEST_EXTENSIONS_SRCDIR) 
>>> $(TEST_EXTENSIONS_TESTS_SRCDIR) "$${testcases_srcs[@]}" \
>>> +      --input-builds $(NETX_DIR)/lib/classes.jar 
>>> $(abs_top_builddir)/liveconnect/lib/classes.jar $(JUNIT_RUNNER_JAR)  
>>> $(TEST_EXTENSIONS_DIR) $(TEST_EXTENSIONS_TESTS_DIR) \
>>> +      --input-srcs  $(NETX_UNIT_TEST_SRCDIR)  \
>>> +      --input-builds $(NETX_UNIT_TEST_DIR)  \
>>> +      --title "IcedTea-Web complete codecoverage" ;
>>> +else
>>> +    echo "Sorry, coverage report cant be run without jacoco 
>>> installed. Try install jacoco or specify with-jacoco value" ;
>>> +    exit 5
>>> +endif
>>> +
>>> +run-test-code-coverage: stamps/run-unit-test-code-coverage.stamps 
>>> stamps/run-reproducers-test-code-coverage.stamps
>>>   if WITH_EMMA
>>>       cd $(TESTS_DIR) ; \
>>>       k=0 ; \
>>> @@ -1175,7 +1392,7 @@
>>>       exit 5
>>>   endif
>>>
>>> -clean-netx-tests: clean-netx-unit-tests clean-junit-runner 
>>> clean-netx-dist-tests clean-test-code-coverage
>>> +clean-netx-tests: clean-netx-unit-tests clean-junit-runner 
>>> clean-netx-dist-tests clean-test-code-coverage-jacoco 
>>> clean-test-code-coverage
>>>       if [ -e $(TESTS_DIR)/netx ]; then \
>>>         rmdir $(TESTS_DIR)/netx ; \
>>>       fi
>>> @@ -1258,6 +1475,44 @@
>>>         rm -f $(TESTS_DIR)/coverage.em ; \
>>>       fi
>>>
>>> +clean-unit-test-code-coverage-jacoco:
>>> +    if [ -e stamps/run-unit-test-code-coverage-jacoco.stamp ]; then \
>>> +      rm -rf $(NETX_UNIT_TEST_DIR)/coverage ; \
>>> +      rm -f $(NETX_UNIT_TEST_DIR)/coverage.xml ; \
>>> +      rm -f $(NETX_UNIT_TEST_DIR)/jacoco.exec ; \
>>> +      rm -f $(NETX_UNIT_TEST_DIR)/tests-output_withEmma.xml ; \
>>> +      rm -f stamps/run-unit-test-code-coverage-jacoco.stamp ; \
>>> +    fi
>>> +
>>> +clean-reproducers-test-code-coverage-jacoco:
>>> +    if [ -e stamps/run-reproducers-test-code-coverage-jacoco.stamp 
>>> ]; then \
>>> +     rm -rf $(TEST_EXTENSIONS_DIR)/coverage-javaws ; \
>>> +     rm -f $(TEST_EXTENSIONS_DIR)/coverage-javaws.xml ; \
>>> +     rm -f $(TEST_EXTENSIONS_DIR)/jacoco_javaws.exec ; \
>>> +     rm -rf $(TEST_EXTENSIONS_DIR)/coverage-plugin ; \
>>> +     rm -f $(TEST_EXTENSIONS_DIR)/coverage-plugin.xml ; \
>>> +     rm -f $(TEST_EXTENSIONS_DIR)/jacoco_plugin.exec ; \
>>> +     rm -rf $(TEST_EXTENSIONS_DIR)/coverage ; \
>>> +     rm -f $(TEST_EXTENSIONS_DIR)/coverage.xml ; \
>>> +     rm -f $(TEST_EXTENSIONS_DIR)/jacoco-merged-reproducers.exec ; \
>>> +     rm -f $(TEST_EXTENSIONS_DIR)/tests-output_withEmma.xml ; \
>>> +     rm -f stamps/run-reproducers-test-code-coverage-jacoco.stamp ; \
>>> +    fi
>>> +
>>> +clean-test-code-coverage-jacoco: 
>>> clean-unit-test-code-coverage-jacoco 
>>> clean-reproducers-test-code-coverage-jacoco 
>>> clean-test-code-coverage-tools-jacoco
>>> +    if [ -e $(TESTS_DIR)/coverage.xml ]; then \
>>> +      rm -rf $(TESTS_DIR)/coverage  ; \
>>> +      rm -f $(TESTS_DIR)/jacoco-merged.exec; \
>>> +    fi
>>> +
>>> +clean-test-code-coverage-tools-jacoco:
>>> +    rm -rf  $(JACOCO_OPERATOR_DIR)
>>> +    rm -rf  $(FAKE_PLUGIN_SRCDIR)
>>> +    rm -rf  $(FAKE_PLUGIN_DIR)
>>> +    rm -f stamps/compile-jacoco-operator.stamp;
>>> +    rm -f jacoco-operator-source-files.txt
>>> +    rm -f stamps/build-fake-plugin.stamp
>>> +
>>>
>>>   # plugin tests
>>>
>>> @@ -1377,3 +1632,7 @@
>>>   run-unit-test-code-coverage: stamps/run-unit-test-code-coverage.stamp
>>>
>>>   run-reproducers-test-code-coverage: 
>>> stamps/run-reproducers-test-code-coverage.stamp
>>> +
>>> +run-unit-test-code-coverage-jacoco: 
>>> stamps/run-unit-test-code-coverage-jacoco.stamp
>>> +
>>> +run-reproducers-test-code-coverage-jacoco: 
>>> stamps/run-reproducers-test-code-coverage-jacoco.stamp
>>> diff -r aff6fb36a9ab configure.ac
>>> --- a/configure.ac    Mon Dec 03 18:08:38 2012 +0100
>>> +++ b/configure.ac    Wed Dec 05 16:40:30 2012 +0100
>>> @@ -106,6 +106,10 @@
>>>       [/usr/share/java/junit4.jar /usr/share/junit-4/lib/junit.jar])
>>>   IT_FIND_OPTIONAL_JAR([emma], EMMA,
>>>       [/usr/share/java/emma.jar])
>>> +IT_FIND_OPTIONAL_JAR([jacoco], JACOCO,
>>> +    [/usr/share/java/jacoco/org.jacoco.core.jar])
>>> +IT_FIND_OPTIONAL_JAR([asm4], ASM4,
>>> +    [/usr/share/java/objectweb-asm4/asm-all-4.0.jar])
>>>
>>>   AC_CONFIG_FILES([jrunscript], [chmod u+x jrunscript])
>>>   AC_CONFIG_FILES([build.properties])
>>>
>>>
>> The makefile grows ... Is it standard practice to have Makefile's 
>> this big ? I think it would be
>> more maintainable and readable with some helper scripts for 
>> test-related parts.
>
> We can maybe put all the testing stuff to different makefile. See the 
> makefiles of openjdk... It is not always an advantage :)  I think this 
> makefile is still ok.

OK, just remember that people get accustomed to less-than-ideal things 
:). (Just like I thought Windows was good-enough until I started using 
linux ...)

>>
>>> diff -r aff6fb36a9ab 
>>> tests/jacoco-operator/org/jacoco/operator/Main.java
>>> --- /dev/null    Thu Jan 01 00:00:00 1970 +0000
>>> +++ b/tests/jacoco-operator/org/jacoco/operator/Main.java Wed Dec 05 
>>> 16:40:30 2012 +0100
>>> @@ -0,0 +1,288 @@
>>> +/*
>>> +Copyright (C) 2012 Red Hat, Inc.
>>> +
>>> +This file is part of IcedTea.
>>> +
>>> +IcedTea is free software; you can redistribute it and/or
>>> +modify it under the terms of the GNU General Public License as 
>>> published by
>>> +the Free Software Foundation, version 2.
>>> +
>>> +IcedTea is distributed in the hope that it will be useful,
>>> +but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +General Public License for more details.
>>> +
>>> +You should have received a copy of the GNU General Public License
>>> +along with IcedTea; see the file COPYING.  If not, write to
>>> +the Free Software Foundation, Inc., 51 Franklin Street, Fifth 
>>> Floor, Boston, MA
>>> +02110-1301 USA.
>>> +
>>> +Linking this library statically or dynamically with other modules is
>>> +making a combined work based on this library.  Thus, the terms and
>>> +conditions of the GNU General Public License cover the whole
>>> +combination.
>>> +
>>> +As a special exception, the copyright holders of this library give you
>>> +permission to link this library with independent modules to produce an
>>> +executable, regardless of the license terms of these independent
>>> +modules, and to copy and distribute the resulting executable under
>>> +terms of your choice, provided that you also meet, for each linked
>>> +independent module, the terms and conditions of the license of that
>>> +module.  An independent module is a module which is not derived from
>>> +or based on this library.  If you modify this library, you may extend
>>> +this exception to your version of the library, but you are not
>>> +obligated to do so.  If you do not wish to do so, delete this
>>> +exception statement from your version.
>>> + */
>>> +
>>> +package org.jacoco.operator;
>>> +
>>> +import java.io.File;
>>> +import java.io.IOException;
>>> +import java.util.ArrayList;
>>> +import java.util.List;
>>> +
>>> +/**
>>> + * Commandline launcher
>>> + */
>>> +public class Main {
>>> +
>>> +    //main switches
>>> +    private static final String MERGE = "merge";
>>> +    private static final String REPORT = "report";
>>> +    //switches
>>> +    private static final String die_soon = "--die-soon";
>>> +    //merge
>>> +    private static final String output_file = "--output-file";
>>> +    private static final String input_files = "--input-files";
>>> +    //report
>>> +    private static final String html_output = "--html-output";
>>> +    private static final String xml_output = "--xml-output";
>>> +    private static final String input_srcs = "--input-srcs";
>>> +    private static final String input_builds = "--input-builds";
>>> +    private static final String title = "--title";
>>> +    private static String input_file = "--input-file";
>>> +    /**
>>> +     * *
>>> +     */
>>> +    private static boolean dieSoon = false;
>>> +    private static boolean warned = false;
>>> +
>>> +    public static void main(String[] args) throws IOException {
>>> +        if (args.length < 2) {
>>> +            printHelp();
>>> +            System.exit(0);
>>> +        }
>>> +
>>> +        Runnable r = null;
>>> +        if (args[0].equalsIgnoreCase(MERGE)) {
>>> +            r = proceedMerge(cutFirstParam(args));
>>> +        } else if (args[0].equalsIgnoreCase(REPORT)) {
>>> +            r = proceedReport(cutFirstParam(args));
>>> +        } else {
>>> +            System.err.println("Unsuported main switch `" + args[0] 
>>> + "`, use " + MERGE + " or " + REPORT);
>>> +            printHelp();
>>> +            System.exit(1);
>>> +        }
>>> +        if (dieSoon && warned) {
>>> +            System.err.println(die_soon + " is specified and 
>>> warning occured. Exiting");
>>> +            System.exit(2);
>>> +        }
>>> +        r.run();
>>> +
>>> +    }
>>> +
>>> +    private static void printHelp() {
>>> +        System.out.println("Usage: java `classapath` 
>>> org.jacoco.operator.Main [" + MERGE + "|" + REPORT + "] 
>>> swithes/files");
>>
>> swithes -> switches
>>
>>> +        System.out.println("    order of swithches does not metter");
>>
>> swithches -> switches

Sorry, just realized that 'metter' should be 'matter' here.

>>
>>> +        System.out.println("  Merge usage: java `classapath` 
>>> org.jacoco.operator.Main " + MERGE + " " + output_file + " file  " + 
>>> input_files + " file file file ...");
>>
>> classapath -> classpath
>>
>>> +        System.out.println("  Report usage: java `classapath` 
>>> org.jacoco.operator.Main " + REPORT + " " + html_output + " file " + 
>>> xml_output + " file  " + input_srcs + " file file file ... " + 
>>> input_builds + " file file file " + title + " titleOfReport " + 
>>> input_file + " file");
>>
>> classapath -> classpath
>>
>>> +        System.out.println("Where:");
>>> +        System.out.println("  classapth should contain this 
>>> application, and complete jacoco, and sometimes asm3 (depends on 
>>> jacoco bundle)");
>>
>> classapth -> classpath
>>
>
>>> +        System.out.println("    " + die_soon + " - can be set as 
>>> firstr parameter (after main switch), each warning then will cause 
>>> exit of application");
>>
>> firstr -> first
>
> All typos should be  fixed
>
>> Maybe 'die_soon' would be more understandable as 'fail_fast' 
>> (die_soon is confusing to me, it is not
>> readily clear that it has to do with failures).
>
> hmhmh I would probably rather prefere die soon. Fil fast looks to me 
> like having nothing to do with dieing, and die_on_failure is to long :)
>
> But I have at least renamed the variable.
>>
>>> +        System.out.println("  " + MERGE);
>>> +        System.out.println("    " + output_file + " - is file where 
>>> merged inputs will be saved");
>>> +        System.out.println("    " + input_files + " - is list of 
>>> files which will be merged into output file");
>>> +        System.out.println("  " + REPORT);
>>> +        System.out.println("    " + html_output + " - name of 
>>> directory into which report will be generated. Should be empty or 
>>> not -existing");
>>
>> 'be empty or not yet exist' is a bit clearer
>>
>>> +        System.out.println("    " + xml_output + " - is name of 
>>> file into which xml report will be written");
>>> +        System.out.println("    " + input_srcs + " - jars, zips or 
>>> directories with java sources which will be used during report 
>>> generation");
>>> +        System.out.println("    " + input_builds + " - jars, zips 
>>> or directories with compiled java classes, debug information must be 
>>> present");
>>> +        System.out.println("    " + title + " - title of report");
>>> +        System.out.println("    " + input_file + " - input file 
>>> with recorded coverage-run-session. By default jacoco saves into " + 
>>> MergeTask.DEFAULT_NAME);
>>> +
>>> +    }
>>> +
>>> +    private static String[] cutFirstParam(String[] args) {
>>> +        String[] arg = new String[args.length - 1];
>>> +        System.arraycopy(args, 1, arg, 0, arg.length);
>>> +        return arg;
>>> +    }
>>> +
>>> +    private static Runnable proceedMerge(String[] a) throws 
>>> IOException {
>>> +        String doing = null;
>>> +        String outputFile = null;
>>> +        List<String> inputFiles = new ArrayList<String>(2);
>>> +        for (String s : a) {
>>> +            if (s.startsWith("--")) {
>>> +                if (s.equalsIgnoreCase(die_soon)) {
>>> +                    doing = null;
>>> +                    dieSoon = true;
>>> +                } else if (s.equalsIgnoreCase(output_file)) {
>>> +                    doing = output_file;
>>> +                } else if (s.equalsIgnoreCase(input_files)) {
>>> +                    doing = input_files;
>>> +                } else {
>>> +                    warnOrDie("Unknown Switch for merge " + s);
>>> +                    doing = null;
>>> +                }
>>> +            } else {
>>> +                if (doing == null) {
>>> +                    warnOrDie("Missing switch during processing of 
>>> " + s);
>>> +                } else {
>>> +                    if (doing.equalsIgnoreCase(output_file)) {
>>> +                        outputFile = s;
>>> +                    } else if (doing.equalsIgnoreCase(input_files)) {
>>> +                        inputFiles.add(s);
>>> +                    } else {
>>> +                        warnOrDie("Unknown processing of switch of" 
>>> + doing);
>>> +                    }
>>> +
>>> +                }
>>> +            }
>>> +        }
>>> +        throwIfNullOrEmpty(outputFile, "empty output file");
>>> +        File ff = new File(outputFile);
>>> +        if (ff.exists()) {
>>> +            warnOrDie("Warning, output file " + 
>>> ff.getAbsolutePath() + " exists");
>>> +        }
>>> +        MergeTask m = new MergeTask(ff);
>>> +        for (String string : inputFiles) {
>>> +            if (checkIfNotNullOrEmpty(string)) {
>>> +                File f = new File(string);
>>> +                if (!f.exists()) {
>>> +                    warnOrDie("Warning, input coverage " + 
>>> f.getAbsolutePath() + " does not exists!");
>>> +                }
>>> +                m.addInputFile(f);
>>> +            }
>>> +        }
>>> +        return m;
>>> +
>>> +    }
>>> +
>>> +    private static Runnable proceedReport(String[] a) throws 
>>> IOException {
>>> +        String doing = null;
>>> +        String htmlDir = null;
>>> +        String xmlFile = null;
>>> +        List<String> inputSrcs = new ArrayList<String>(1);
>>> +        List<String> inputBuilds = new ArrayList<String>(1);
>>> +        String titleValue = null;
>>> +        String inputFile = null;
>>> +        for (String s : a) {
>>> +            if (s.startsWith("--")) {
>>> +                if (s.equalsIgnoreCase(die_soon)) {
>>> +                    doing = null;
>>> +                    dieSoon = true;
>>> +                } else if (s.equalsIgnoreCase(html_output)) {
>>> +                    doing = html_output;
>>> +                } else if (s.equalsIgnoreCase(xml_output)) {
>>> +                    doing = xml_output;
>>> +                } else if (s.equalsIgnoreCase(input_srcs)) {
>>> +                    doing = input_srcs;
>>> +                } else if (s.equalsIgnoreCase(input_builds)) {
>>> +                    doing = input_builds;
>>> +                } else if (s.equalsIgnoreCase(title)) {
>>> +                    doing = title;
>>> +                } else if (s.equalsIgnoreCase(input_file)) {
>>> +                    doing = input_file;
>>> +                } else {
>>> +                    warnOrDie("Unknown Switch for report " + s);
>>> +                    doing = null;
>>> +                }
>>> +            } else {
>>> +                if (doing == null) {
>>> +                    warnOrDie("Missing switch during processing of 
>>> " + s);
>>> +                } else {
>>> +                    if (doing.equalsIgnoreCase(html_output)) {
>>> +                        htmlDir = s;
>>> +                    } else if (doing.equalsIgnoreCase(xml_output)) {
>>> +                        xmlFile = s;
>>> +                    } else if (doing.equalsIgnoreCase(input_srcs)) {
>>> +                        inputSrcs.add(s);
>>> +                    } else if (doing.equalsIgnoreCase(input_builds)) {
>>> +                        inputBuilds.add(s);
>>> +                    } else if (doing.equalsIgnoreCase(title)) {
>>> +                        titleValue = s;
>>> +                    } else if (doing.equalsIgnoreCase(input_file)) {
>>> +                        inputFile = s;
>>> +                    } else {
>>> +                        warnOrDie("Unknown processing of switch of 
>>> " + doing);
>>> +                    }
>>> +
>>> +                }
>>> +            }
>>> +        }
>>> +        File finalHtmlFile = null;
>>> +        if (checkIfNotNullOrEmpty(htmlDir)) {
>>> +            finalHtmlFile = new File(htmlDir);
>>> +            if (finalHtmlFile.exists()) {
>>> +                warnOrDie("Warning, direcotry for html report 
>>> exists! " + finalHtmlFile.getAbsolutePath());
>>> +            }
>>> +        }
>>> +        File finalXmlFile = null;
>>> +        if (checkIfNotNullOrEmpty(xmlFile)) {
>>> +            finalXmlFile = new File(xmlFile);
>>> +            if (finalXmlFile.exists()) {
>>> +                warnOrDie("Warning, file for xml report exists! " + 
>>> finalHtmlFile.getAbsolutePath());
>>> +            }
>>> +        }
>>> +        if (chckIfNUllOrEmpty(titleValue)) {
>>> +            titleValue = "Coverage report";
>>> +        }
>>> +        throwIfNullOrEmpty(inputFile, "No coverage data file 
>>> specified!");
>>> +        File finalInputFile = new File(inputFile);
>>> +
>>> +        ReportGenerator rg = new ReportGenerator(titleValue, 
>>> finalInputFile, finalHtmlFile, finalXmlFile);
>>> +
>>> +        for (String string : inputSrcs) {
>>> +            if (checkIfNotNullOrEmpty(string)) {
>>> +                File f = new File(string);
>>> +                if (!f.exists()) {
>>> +                    warnOrDie("Warning, input source " + 
>>> f.getAbsolutePath() + " does not exists!");
>>> +                }
>>> +                rg.addSource(f);
>>> +            }
>>> +        }
>>> +        for (String string : inputBuilds) {
>>> +            if (checkIfNotNullOrEmpty(string)) {
>>> +                File f = new File(string);
>>> +                if (!f.exists()) {
>>> +                    warnOrDie("Warning, input build " + 
>>> f.getAbsolutePath() + " does not exists!");
>>> +                }
>>> +                rg.addClasses(f);
>>> +            }
>>> +        }
>>> +        return rg;
>>> +    }
>>> +
>>> +    private static String throwIfNullOrEmpty(String outputFile, 
>>> String message) throws RuntimeException {
>>> +        if (chckIfNUllOrEmpty(outputFile)) {
>>> +            throw new RuntimeException(message);
>>> +        }
>>> +        return outputFile;
>>> +    }
>>> +
>>> +    private static boolean checkIfNotNullOrEmpty(String string) {
>>> +        return string != null && string.trim().length() != 0;
>>> +    }
>>> +
>>> +    private static boolean chckIfNUllOrEmpty(String outputFile) {
>>> +        return outputFile == null || outputFile.trim().length() == 0;
>>> +    }
>>> +
>>> +    private static void warnOrDie(String string) {
>>> +        System.err.println(string);
>>> +        warned = true;
>>> +
>>> +    }
>>> +}
>>
>> Nice little tool overall
>
> jsut full of typos :-/
> Thanx!
>
> I hope after this spell check it will b eupstreamed faster :D
>
>>
>>> diff -r aff6fb36a9ab 
>>> tests/jacoco-operator/org/jacoco/operator/MergeTask.java
>>> --- /dev/null    Thu Jan 01 00:00:00 1970 +0000
>>> +++ b/tests/jacoco-operator/org/jacoco/operator/MergeTask.java Wed 
>>> Dec 05 16:40:30 2012 +0100
>>> @@ -0,0 +1,169 @@
>>> +/*
>>> +Copyright (C) 2012 Red Hat, Inc.
>>> +
>>> +This file is part of IcedTea.
>>> +
>>> +IcedTea is free software; you can redistribute it and/or
>>> +modify it under the terms of the GNU General Public License as 
>>> published by
>>> +the Free Software Foundation, version 2.
>>> +
>>> +IcedTea is distributed in the hope that it will be useful,
>>> +but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +General Public License for more details.
>>> +
>>> +You should have received a copy of the GNU General Public License
>>> +along with IcedTea; see the file COPYING.  If not, write to
>>> +the Free Software Foundation, Inc., 51 Franklin Street, Fifth 
>>> Floor, Boston, MA
>>> +02110-1301 USA.
>>> +
>>> +Linking this library statically or dynamically with other modules is
>>> +making a combined work based on this library.  Thus, the terms and
>>> +conditions of the GNU General Public License cover the whole
>>> +combination.
>>> +
>>> +As a special exception, the copyright holders of this library give you
>>> +permission to link this library with independent modules to produce an
>>> +executable, regardless of the license terms of these independent
>>> +modules, and to copy and distribute the resulting executable under
>>> +terms of your choice, provided that you also meet, for each linked
>>> +independent module, the terms and conditions of the license of that
>>> +module.  An independent module is a module which is not derived from
>>> +or based on this library.  If you modify this library, you may extend
>>> +this exception to your version of the library, but you are not
>>> +obligated to do so.  If you do not wish to do so, delete this
>>> +exception statement from your version.
>>> + */
>>> +package org.jacoco.operator;
>>> +
>>> +import java.io.BufferedOutputStream;
>>> +import java.io.File;
>>> +import java.io.FileInputStream;
>>> +import java.io.FileOutputStream;
>>> +import java.io.IOException;
>>> +import java.io.InputStream;
>>> +import java.io.OutputStream;
>>> +import java.util.ArrayList;
>>> +import java.util.Iterator;
>>> +import java.util.List;
>>> +import org.jacoco.core.data.ExecutionDataReader;
>>> +import org.jacoco.core.data.ExecutionDataStore;
>>> +import org.jacoco.core.data.ExecutionDataWriter;
>>> +import org.jacoco.core.data.SessionInfoStore;
>>> +
>>> +/**
>>> + * Task for merging a set of execution data store files into a 
>>> single file
>>> + *
>>> + * Inspired by:
>>> + 
>>> *https://raw.github.com/jacoco/jacoco/master/org.jacoco.ant/src/org/jacoco/ant/MergeTask.java
>>> + */
>>> +public class MergeTask implements Runnable {
>>> +
>>> +    public static final String DEFAULT_NAME = "jacoco.exec";
>>> +    private File destfile;
>>> +    private final List<File> files = new ArrayList<File>(1);
>>> +
>>> +    public MergeTask(File destfile) {
>>> +        this.destfile = destfile;
>>> +    }
>>> +
>>> +    public MergeTask(File destfile, List<File> inputs) {
>>> +        this.destfile = destfile;
>>> +        files.addAll(inputs);
>>> +    }
>>> +
>>> +    /**
>>> +     * Sets the location of the merged data store
>>> +     *
>>> +     * @param destfile Destination data store location
>>> +     */
>>> +    public void setDestfile(final File destfile) {
>>> +        this.destfile = destfile;
>>> +    }
>>> +
>>> +    public void addInputFile(final File input) {
>>> +        if (input != null) {
>>> +            files.add(input);
>>> +        }
>>> +    }
>>> +
>>> +    public void addInputFiles(final List<File> input) {
>>> +        files.addAll(input);
>>> +    }
>>> +
>>> +    public void execute() throws IOException {
>>> +        if (destfile == null) {
>>> +            throw new RuntimeException("Destination file must be 
>>> supplied");
>>> +        }
>>> +
>>> +        final SessionInfoStore infoStore = new SessionInfoStore();
>>> +        final ExecutionDataStore dataStore = new ExecutionDataStore();
>>> +
>>> +        loadSourceFiles(infoStore, dataStore);
>>> +
>>> +        OutputStream outputStream = null;
>>> +        try {
>>> +
>>> +            outputStream = new BufferedOutputStream(new 
>>> FileOutputStream(
>>> +                    destfile));
>>> +            final ExecutionDataWriter dataWriter = new 
>>> ExecutionDataWriter(
>>> +                    outputStream);
>>> +            infoStore.accept(dataWriter);
>>> +            dataStore.accept(dataWriter);
>>> +        } finally {
>>> +            if (outputStream != null) {
>>> +                outputStream.close();
>>> +            }
>>> +        }
>>> +
>>> +    }
>>> +
>>> +    private void loadSourceFiles(final SessionInfoStore infoStore, 
>>> final ExecutionDataStore dataStore) throws IOException {
>>> +        if (files == null || files.isEmpty()) {
>>> +            throw new RuntimeException("No input files");
>>> +        }
>>> +        final Iterator<?> resourceIterator = files.iterator();
>>> +        while (resourceIterator.hasNext()) {
>>> +            final File resource = (File) resourceIterator.next();
>>> +
>>> +            if (resource.isDirectory()) {
>>> +                continue;
>>> +            }
>>> +            InputStream resourceStream = null;
>>> +            try {
>>> +                resourceStream = new FileInputStream(resource);
>>> +                final ExecutionDataReader reader = new 
>>> ExecutionDataReader(
>>> +                        resourceStream);
>>> +                reader.setSessionInfoVisitor(infoStore);
>>> +                reader.setExecutionDataVisitor(dataStore);
>>> +                reader.read();
>>> +            } finally {
>>> +                if (resourceStream != null) {
>>> +                    resourceStream.close();
>>> +                }
>>> +            }
>>> +        }
>>> +    }
>>> +
>>> +    @Override
>>> +    public void run() {
>>> +        try {
>>> +            execute();
>>> +        } catch (IOException ex) {
>>> +            throw new RuntimeException(ex);
>>> +        }
>>> +    }
>>> +
>>> +    public static void main(final String[] args) throws IOException {
>>> +        String root = 
>>> "/home/jvanek/Desktop/icedtea-web/tests.build/netx/unit/";
>>> +        String result = root+"/jacoco-merged.exec";
>>> +        String file =root + "/"+DEFAULT_NAME;
>>> +
>>> +
>>> +        final MergeTask merger = new MergeTask(new File(result));
>>> +        merger.addInputFile(new File(file));
>>> +        merger.addInputFile(new File(file));
>>> +        merger.execute();
>>> +
>>> +    }
>>> +}
>>> diff -r aff6fb36a9ab 
>>> tests/jacoco-operator/org/jacoco/operator/ReportGenerator.java
>>> --- /dev/null    Thu Jan 01 00:00:00 1970 +0000
>>> +++ b/tests/jacoco-operator/org/jacoco/operator/ReportGenerator.java 
>>> Wed Dec 05 16:40:30 2012 +0100
>>> @@ -0,0 +1,336 @@
>>> +/*
>>> +Copyright (C) 2012 Red Hat, Inc.
>>> +
>>> +This file is part of IcedTea.
>>> +
>>> +IcedTea is free software; you can redistribute it and/or
>>> +modify it under the terms of the GNU General Public License as 
>>> published by
>>> +the Free Software Foundation, version 2.
>>> +
>>> +IcedTea is distributed in the hope that it will be useful,
>>> +but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>> +General Public License for more details.
>>> +
>>> +You should have received a copy of the GNU General Public License
>>> +along with IcedTea; see the file COPYING.  If not, write to
>>> +the Free Software Foundation, Inc., 51 Franklin Street, Fifth 
>>> Floor, Boston, MA
>>> +02110-1301 USA.
>>> +
>>> +Linking this library statically or dynamically with other modules is
>>> +making a combined work based on this library.  Thus, the terms and
>>> +conditions of the GNU General Public License cover the whole
>>> +combination.
>>> +
>>> +As a special exception, the copyright holders of this library give you
>>> +permission to link this library with independent modules to produce an
>>> +executable, regardless of the license terms of these independent
>>> +modules, and to copy and distribute the resulting executable under
>>> +terms of your choice, provided that you also meet, for each linked
>>> +independent module, the terms and conditions of the license of that
>>> +module.  An independent module is a module which is not derived from
>>> +or based on this library.  If you modify this library, you may extend
>>> +this exception to your version of the library, but you are not
>>> +obligated to do so.  If you do not wish to do so, delete this
>>> +exception statement from your version.
>>> + */
>>> +
>>> +package org.jacoco.operator;
>>> +
>>> +import java.io.File;
>>> +import java.io.FileInputStream;
>>> +import java.io.FileOutputStream;
>>> +import java.io.IOException;
>>> +import java.io.OutputStream;
>>> +import java.util.ArrayList;
>>> +import java.util.List;
>>> +import org.jacoco.core.analysis.Analyzer;
>>> +import org.jacoco.core.analysis.CoverageBuilder;
>>> +import org.jacoco.core.analysis.IBundleCoverage;
>>> +import org.jacoco.core.data.ExecutionDataReader;
>>> +import org.jacoco.core.data.ExecutionDataStore;
>>> +import org.jacoco.core.data.SessionInfoStore;
>>> +import org.jacoco.report.DirectorySourceFileLocator;
>>> +import org.jacoco.report.FileMultiReportOutput;
>>> +import org.jacoco.report.IReportVisitor;
>>> +import org.jacoco.report.MultiSourceFileLocator;
>>> +import org.jacoco.report.html.HTMLFormatter;
>>> +import org.jacoco.report.xml.XMLFormatter;
>>> +
>>> +/**
>>> + * This example creates a HTML report for eclipse like projects 
>>> based on a
>>> + * single execution data store called jacoco.exec. The report 
>>> contains no
>>> + * grouping information.
>>> + *
>>> + * The class files under test must be compiled with debug 
>>> information, otherwise
>>> + * source highlighting will not work.
>>> + *
>>> + * Originally based on:
>>> + 
>>> *http://www.eclemma.org/jacoco/trunk/doc/examples/java/ReportGenerator.java
>>> + */
>>> +public class ReportGenerator implements Runnable {
>>> +
>>> +    private final String title;
>>> +    private final File executionDataFile;
>>> +    private final List<File> classesDirectories = new 
>>> ArrayList<File>(1);
>>> +    private final List<File> sourceDirectories = new 
>>> ArrayList<File>(1);
>>> +    private File reportDirectory;
>>> +    private File xmlOutput;
>>> +    private ExecutionDataStore executionDataStore;
>>> +    private SessionInfoStore sessionInfoStore;
>>> +    private String XML_DEF_NAME = "coverage-summary.xml";
>>> +
>>> +    /**
>>> +     * Create a new generator based for the given project.
>>> +     *
>>> +     * @param projectDirectory
>>> +     */
>>> +    public ReportGenerator(final File projectDirectory) {
>>> +        this.title = projectDirectory.getName();
>>> +        this.executionDataFile = new File(projectDirectory, 
>>> MergeTask.DEFAULT_NAME);
>>> +        this.classesDirectories.add(new File(projectDirectory, 
>>> "bin"));
>>> +        this.sourceDirectories.add(new File(projectDirectory, "src"));
>>> +        this.reportDirectory = new File(projectDirectory, 
>>> "coveragereport");
>>> +        this.xmlOutput = new File(projectDirectory, XML_DEF_NAME);
>>> +    }
>>> +
>>> +    public ReportGenerator(String title, File exec, File classes, 
>>> File sources, File htmlReport, File xmlReport) {
>>> +        this.title = title;
>>> +        this.executionDataFile = exec;
>>> +        if (classes != null) {
>>> +            this.classesDirectories.add(classes);
>>> +        }
>>> +        if (sources != null) {
>>> +            this.sourceDirectories.add(sources);
>>> +        }
>>> +        this.reportDirectory = htmlReport;
>>> +
>>> +        this.xmlOutput = xmlReport;
>>> +    }
>>> +
>>> +    public ReportGenerator(String title, File exec, List<File> 
>>> classes, List<File> sources, File htmlReport, File xmlReport) {
>>> +        this.title = title;
>>> +        this.executionDataFile = exec;
>>> +        if (classes != null) {
>>> +            this.classesDirectories.addAll(classes);
>>> +        }
>>> +        if (sources != null) {
>>> +            this.sourceDirectories.addAll(sources);
>>> +        }
>>> +        this.reportDirectory = htmlReport;
>>> +        this.xmlOutput = xmlReport;
>>> +    }
>>> +
>>> +    public ReportGenerator(String title, File exec, List<File> 
>>> classes, List<File> sources, File report) {
>>> +        this.title = title;
>>> +        this.executionDataFile = exec;
>>> +        if (classes != null) {
>>> +            this.classesDirectories.addAll(classes);
>>> +        }
>>> +        if (sources != null) {
>>> +            this.sourceDirectories.addAll(sources);
>>> +        }
>>> +        this.reportDirectory = report;
>>> +        this.xmlOutput = new File(report, XML_DEF_NAME);
>>> +    }
>>> +
>>> +    public ReportGenerator(String title, File exec, File 
>>> htmlReport, File xmlReport) {
>>> +        this.title = title;
>>> +        this.executionDataFile = exec;
>>> +        this.reportDirectory = htmlReport;
>>> +        this.xmlOutput = xmlReport;
>>> +    }
>>> +
>>> +    public ReportGenerator(String title, File exec, File report) {
>>> +        this.title = title;
>>> +        this.executionDataFile = exec;
>>> +        this.reportDirectory = report;
>>> +        this.xmlOutput = new File(report, XML_DEF_NAME);
>>> +    }
>>> +
>>> +    public void addSource(File f) {
>>> +        sourceDirectories.add(f);
>>> +
>>> +    }
>>> +
>>> +    public void addClasses(File f) {
>>> +        classesDirectories.add(f);
>>> +
>>> +    }
>>> +
>>> +    /**
>>> +     * Create the report.
>>> +     *
>>> +     * @throws IOException
>>> +     */
>>> +    public void execute() throws IOException {
>>> +
>>> +        // Read the jacoco.exec file. Multiple data stores could be 
>>> merged
>>> +        // at this point
>>> +        loadExecutionData();
>>> +
>>> +        // Run the structure analyzer on a single class folder to 
>>> build up
>>> +        // the coverage model. The process would be similar if your 
>>> classes
>>> +        // were in a jar file. Typically you would create a bundle 
>>> for each
>>> +        // class folder and each jar you want in your report. If 
>>> you have
>>> +        // more than one bundle you will need to add a grouping 
>>> node to your
>>> +        // report
>>> +        final IBundleCoverage bundleCoverage = analyzeStructure();
>>> +
>>> +        if (reportDirectory != null) {
>>> +            createHtmlReport(bundleCoverage);
>>> +        }
>>> +        if (xmlOutput != null) {
>>> +            createXmlReport(bundleCoverage);
>>> +        }
>>> +
>>> +    }
>>> +
>>> +    private void createHtmlReport(final IBundleCoverage 
>>> bundleCoverage)
>>> +            throws IOException {
>>> +
>>> +        // Create a concrete report visitor based on some supplied
>>> +        // configuration. In this case we use the defaults
>>> +        final HTMLFormatter htmlFormatter = new HTMLFormatter();
>>> +        final IReportVisitor visitor = 
>>> htmlFormatter.createVisitor(new 
>>> FileMultiReportOutput(reportDirectory));
>>> +
>>> +        // Initialize the report with all of the execution and session
>>> +        // information. At this point the report doesn't know about 
>>> the
>>> +        // structure of the report being created
>>> +        visitor.visitInfo(sessionInfoStore.getInfos(),
>>> +                executionDataStore.getContents());
>>> +
>>> +        // Populate the report structure with the bundle coverage 
>>> information.
>>> +        // Call visitGroup if you need groups in your report.
>>> +        MultiSourceFileLocator msf = new MultiSourceFileLocator(4);
>>> +        for (File file : sourceDirectories) {
>>> +            msf.add(new DirectorySourceFileLocator(
>>> +                    file, "utf-8", 4));
>>> +        }
>>> +
>>> +        visitor.visitBundle(bundleCoverage, msf);
>>> +
>>> +        // Signal end of structure information to allow report to 
>>> write all
>>> +        // information out
>>> +        visitor.visitEnd();
>>> +
>>> +    }
>>> +
>>> +    private void createXmlReport(final IBundleCoverage bundleCoverage)
>>> +            throws IOException {
>>> +
>>> +        OutputStream fos = new FileOutputStream(xmlOutput);
>>> +        try {
>>> +            // Create a concrete report visitor based on some supplied
>>> +            // configuration. In this case we use the defaults
>>> +            final XMLFormatter htmlFormatter = new XMLFormatter();
>>> +            final IReportVisitor visitor = 
>>> htmlFormatter.createVisitor(fos);
>>> +
>>> +            // Initialize the report with all of the execution and 
>>> session
>>> +            // information. At this point the report doesn't know 
>>> about the
>>> +            // structure of the report being created
>>> +            visitor.visitInfo(sessionInfoStore.getInfos(),
>>> +                    executionDataStore.getContents());
>>> +
>>> +            // Populate the report structure with the bundle 
>>> coverage information.
>>> +            // Call visitGroup if you need groups in your report.
>>> +            visitor.visitBundle(bundleCoverage, null);
>>> +
>>> +
>>> +            // Signal end of structure information to allow report 
>>> to write all
>>> +            // information out
>>> +            visitor.visitEnd();
>>> +        } finally {
>>> +            if (fos != null) {
>>> +                fos.close();
>>> +            }
>>> +        }
>>> +
>>> +    }
>>> +
>>> +    private void loadExecutionData() throws IOException {
>>> +        final FileInputStream fis = new 
>>> FileInputStream(executionDataFile);
>>> +        try {
>>> +            final ExecutionDataReader executionDataReader = new 
>>> ExecutionDataReader(
>>> +                    fis);
>>> +            executionDataStore = new ExecutionDataStore();
>>> +            sessionInfoStore = new SessionInfoStore();
>>> +
>>> + executionDataReader.setExecutionDataVisitor(executionDataStore);
>>> + executionDataReader.setSessionInfoVisitor(sessionInfoStore);
>>> +
>>> +            while (executionDataReader.read()) {
>>> +            }
>>> +        } finally {
>>> +            if (fis != null) {
>>> +                fis.close();
>>> +            }
>>> +        }
>>> +    }
>>> +
>>> +    private IBundleCoverage analyzeStructure() throws IOException {
>>> +        final CoverageBuilder coverageBuilder = new CoverageBuilder();
>>> +        final Analyzer analyzer = new Analyzer(executionDataStore,
>>> +                coverageBuilder);
>>> +        for (File file : classesDirectories) {
>>> +            analyzer.analyzeAll(file);
>>> +
>>> +        }
>>> +
>>> +        return coverageBuilder.getBundle(title);
>>> +    }
>>> +
>>> +    @Override
>>> +    public void run() {
>>> +        try {
>>> +            execute();
>>> +        } catch (IOException ex) {
>>> +            throw new RuntimeException(ex);
>>> +        }
>>> +    }
>>> +
>>> +    public static void main(final String[] args) throws IOException {
>>> +        String root = "/home/jvanek/Desktop/icedtea-web/";
>>
>> There's maybe a slight chance someone else will want to run this :))
>>
>>> +
>>> +        String src1 = root + "netx/";
>>> +        String src2 = root + "plugin/icedteanp/java/";
>>> +        String src3 = root + "tests/test-extensions/";
>>> +        String src4 = root + "tests/test-extensions-tests/";
>>> +        String src5 = root + "tests/netx/unit/";
>>> +        String src6 = root + "tests/junit-runner/";
>>
>> I'd say either give these descriptive names or do something like:
>>
>> String[] sources = {"netx/", ...}; and
>>
>> for (String s : sources) {
>>    sourceDirectories.add(new File(root + s));
>> }
>>
>>
>>> +        //reproducers srcs+testcases
>>> +
>>> +        String cls1 = root + "netx.build/lib/classes.jar";
>>> +        String cls2 = root + "liveconnect/lib/classes.jar";
>>> +        String cls3 = root + "tests.build/test-extensions/";
>>> +        //??String cls4=root+"tests/test-extensions-tests/";
>>> +        String cls5 = root + "tests.build/netx/unit/";
>>> +        String cls6 = root + "tests.build/junit-runner/";
>>
>> As above, numbered variable names are a code smell IMO.
>>
>>> +        //reproducers jars and testcases
>>> +
>>> +
>>> +
>>> +        final List<File> sourceDirectories = new ArrayList<File>(10);
>>> +        sourceDirectories.add(new File(src1));
>>> +        sourceDirectories.add(new File(src2));
>>> +        sourceDirectories.add(new File(src3));
>>> +        sourceDirectories.add(new File(src4));
>>> +        sourceDirectories.add(new File(src5));
>>> +        sourceDirectories.add(new File(src6));
>>> +
>>> +        final List<File> classesDirectories = new ArrayList<File>(10);
>>> +        classesDirectories.add(new File(cls1));
>>> +        classesDirectories.add(new File(cls2));
>>> +        classesDirectories.add(new File(cls3));
>>> +        classesDirectories.add(new File(cls5));
>>> +        classesDirectories.add(new File(cls6));
>>> +
>>> +
>>> +        final ReportGenerator generator = new ReportGenerator(
>>> +                "icedtea-web coverage report",
>>> +                new File(cls5 + "/" + MergeTask.DEFAULT_NAME), 
>>> classesDirectories, sourceDirectories,
>>> +                new File(root + "unit-report"));
>>> +        generator.execute();
>>> +
>>> +    }
>>> +}
>>>
>
> Both main methods removed. SHould not be here....
>>
>>
>>> diff -r aff6fb36a9ab tests/plugin_fakeing.patch
>>> --- /dev/null    Thu Jan 01 00:00:00 1970 +0000
>>> +++ b/tests/plugin_fakeing.patch    Wed Dec 05 16:40:30 2012 +0100
>>> @@ -0,0 +1,31 @@
>>> +--- IcedTeaNPPlugin.cc
>>> ++++ IcedTeaNPPlugin.cc
>>> +@@ -1623,12 +1623,13 @@
>>> +   int cmd_num = 0;
>>> +   if (plugin_debug)
>>> +   {
>>> +-      command_line = (gchar**) malloc(sizeof(gchar*)*11);
>>> ++      command_line = (gchar**) malloc(sizeof(gchar*)*12);
>>> +       command_line[cmd_num++] = g_strdup(appletviewer_executable);
>>> +       command_line[cmd_num++] = g_strdup(PLUGIN_BOOTCLASSPATH);
>>> +       // set the classpath to avoid using the default (cwd).
>>> +       command_line[cmd_num++] = g_strdup("-classpath");
>>> +       command_line[cmd_num++] = g_strdup_printf("%s/lib/rt.jar", 
>>> ICEDTEA_WEB_JRE);
>>> ++      command_line[cmd_num++] = g_strdup(COVERAGE_AGENT);
>>> +       command_line[cmd_num++] = g_strdup("-Xdebug");
>>> +       command_line[cmd_num++] = g_strdup("-Xnoagent");
>>> +       if (plugin_debug_suspend)
>>> +@@ -1644,11 +1645,12 @@
>>> +       command_line[cmd_num] = NULL;
>>> +   } else
>>> +   {
>>> +-      command_line = (gchar**) malloc(sizeof(gchar*)*8);
>>> ++      command_line = (gchar**) malloc(sizeof(gchar*)*9);
>>> +       command_line[cmd_num++] = g_strdup(appletviewer_executable);
>>> +       command_line[cmd_num++] = g_strdup(PLUGIN_BOOTCLASSPATH);
>>> +       command_line[cmd_num++] = g_strdup("-classpath");
>>> +       command_line[cmd_num++] = g_strdup_printf("%s/lib/rt.jar", 
>>> ICEDTEA_WEB_JRE);
>>> ++      command_line[cmd_num++] = g_strdup(COVERAGE_AGENT);
>>> +       command_line[cmd_num++] = g_strdup("sun.applet.PluginMain");
>>> +       command_line[cmd_num++] = g_strdup(out_pipe_name);
>>> +       command_line[cmd_num++] = g_strdup(in_pipe_name);
>>
>> I think we could do better by having an ifdef here for 
>> COVERAGE_AGENT, eg (based off HEAD), attached
>> is an example patch that accomplishes this (as well as merging the 
>> duplicate code, so I didn't have
>> to add it in two places). This will not require patching of the 
>> source tree, the extra define passed
>> will suffice. You will be able to work off the original source this way.
>
> As we agreed  on irc, definitely :)
>
> btw.. I hope you are right with c++ pathc you suggested and I have 
> blindly used :)

Should be fine, although if were completely technical its 'unreviewed' :)
So much for example patch :)

>
>>
>> Happy hacking,
>> -Adam
>

So final consensus is you can push (only issue I saw was the 
metter->matter typo) ... if you really don't want to start involving 
bash files in our build process -- however I think organization is 
always a good thing. I'll leave it up to you as you have experience 
trying this in the past.

OKish for HEAD :)

Happy hacking,
-Adam



More information about the distro-pkg-dev mailing list