This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 29434 - add support for IDE testability
Summary: add support for IDE testability
Status: RESOLVED FIXED
Alias: None
Product: platform
Classification: Unclassified
Component: -- Other -- (show other bugs)
Version: 3.x
Hardware: All All
: P2 blocker (vote)
Assignee: issues@platform
URL:
Keywords: T9Y
Depends on:
Blocks:
 
Reported: 2002-12-10 13:20 UTC by Martin Brehovsky
Modified: 2008-12-22 18:01 UTC (History)
3 users (show)

See Also:
Issue Type: ENHANCEMENT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Brehovsky 2002-12-10 13:20:25 UTC
To make testability of IDE more robust and more
'official' I'd like to propose some enhancements.
which will be utilized primarily by XTest harness.
XTest (or any other module used for testing)
should be designed as an IDE module, but such
module should have additional privileges / access
to additional functionality, which should not be
used by any standard module:

1: Testing frameworks need sometimes to add 3rd
party libraries (which are not distributed with
IDE, e.g. JDBC drivers, JNDI providers ...) to IDE
installation, so they can successfully test all
necessary features. Currently these libraries have
to be copied to ${netbeans.home}/lib/ext library.
Because testing frameworks usually runs several
independent tests on a single IDE installation,
nothing in the ${netbeans.home} directory should
be changed. All the required libraries and jars
should be copied rather to ${user.home} dir, which
is created new for each IDE session. Currently
this works for modules/ subdirectory and probably
some more, but I'm not sure if this works also
with lib/ subdirectory, it should work as well.

2: When specified in a defined system property
(netbeans.startup.method?), IDE should be able to
start a static method from a defined class on a
classpath ASAP (definitely before IDE or any
modules are initialized). This mechanism should be
used to perform some necessary initialization of
testing frameworks. XTest would use this mechanism
to get PID of running IDE, because the only way
how to destroy deadlocked IDE is to call kill
-SIGKILL or equivalents system calls.

3: When IDE is fully initialized, there is a need
to somehow start the testing process. Prior the
testing process itself, it os usually required to
perform some additional setup actions via open api
of either openide and/or some other modules
(projects or java for example). Considering XTest
is a module and it will need to access a module
api, this usually means it should depend on this
module. I'm just wondering if this can be done
rather dynamically, since in the case of IDE
platform, there does not have to be projects or
java modules, and it is highly inconvenient to
create several distributions of the testing
framework, where one depends on the projects
module and the other does not. It would be
definitely better to discover the presence of the
module dynamically and decide in the testing
module what to do.

4: Testing frameworks need also to load and run
tests. Unfortunately tests usually need to access
api of several modules at once, but usually
without defining dependency on them. Tests also
need to have access to libraries supplied with the
testing frameworks (in the case of XTest junit.jar
and junit-ext.jar, sometimes jemmy.jar and
jelly.jar). These libraries could also depend on
some other IDE modules. Currently, in the case of
XTest, is this achieved by mounting tests to
filesystem repository and executing them via
internal execution, but this is definitely not the
best way how to load tests. Ideally, testing
frameworks should be able to specify a
classloader, which will be used for loading the
tests. Currently, there are three known ways how
testing framework should load tests (the modes are
intended as mutually exclusive  - test developer
need to decide which he would like to use):
	4.1: Tests need to access openide and apis from
other API modules (e.g. java, cvs ...). This is
basically the same level of access as is currently
available for java code mounted in repository and
executed internally.
	4.2: Tests need to access package private methods
of am IDE module -> they need to be loaded by the
same classloader as is used for loading to be
tested module. Please note, in this case tests
still need access to testing frameworks libraries
(e.g. junit.jar, ...).
	4.3: Tests need to access package private methods
of openide/core classes which are not in any
modules (stuff in lib/). As in the previous mode,
they need to be loaded by the same classloader as
openide/core classes, but still need access to the
testing libraries.
Comment 1 _ ttran 2003-01-03 15:37:51 UTC
Jesse, can you please evaluate this issue?  How much work does it mean
for developers and who in nb-core (besides you :-( would be able to do
the impl?  QA is very interested in having this RFE done.  Thanks
Comment 2 Jesse Glick 2003-01-06 18:41:18 UTC
Re. #1 - $userdir/lib/ext/ is not used currently and I do not plan to
use it. Choice of userdir should not affect early startup; want to
leave open the option of selecting a userdir at runtime after early
initialization. Rather you should use the -cp:a switch.

Re. #2 - does not sound difficult. Basically a startup hook. Perhaps
included in org.netbeans.Main.

Re. #3 - I imagine you can do this already, what specifically are you
asking for?

Re. #4.1 - yes this is easy and already supported using the
netbeans.systemclassloader.patches system property, for example. I
dislike your suggestion to mount test sources in the Repository and
use internal execution. This is using an inappropriate tool for the
problem and is more work than you need, as well as being potentially
unreliable. Simply create a URLClassLoader parented to
systemClassLoader and load what you want, that is much easier.

Re. #4.2 and #4.3 - you can use netbeans.patches.code.name.base.here
and -cp:a to run tests from whatever loader you desire. If they need
access to the testing libraries, then I guess the testing libraries
will need to be in the startup classpath - which means no access to
openide, note, which may mean you have to clean up XTest to not
require openide classes at runtime (I don't see why they should be
needed anyway).

So so far the only thing I see core needing to provide that it does
not already provide is #2, which should be quite trivial (a few lines
of code), plus core or xtest developers need to document which hooks
are used by XTest and maybe have some kind of stripped-down test which
just checks that all those hooks are still working.
Comment 3 Martin Brehovsky 2003-01-07 14:48:38 UTC
Re #1: OK, XTest can use -cp:a for jdbc drivers and jndi providers,
but where actually these jars should an ordinary user put? Ideally, I
would like to use the same way for this in XTest, as users will use
when using JDBC or JNDI for development in IDE.

#2: OK. Where will have to be stored the class containing the static
method? In lib/? Would it be possible to store it somewhere else than
directly in netbeans.home/? 

#3: yes, XTest currently uses netbeans.mainclass system property to
supply it's own Main class to core. But this class has to be loaded by
the boot classloader, therefore it has to be copied to lib/ directory.
I wanted to ask if something like this can be done when XTest is a
module (i.e. nothing is copied to lib/ and the module is stored in
modules/). When you look at #2, I just need to perform some settings
ASAP some code of IDE is running. This code should not contain any
openide/core calls (since most of the stuff is not yet initialized).
Then when IDE is fully initialized, I will need to perform some other
actions, this time with have usage of openide/core and possible of
projects/java/... as well.  By combination of #2 and #3 I was thinking
I could divide XTest into two parts - one is IDE independent, but
needs to be loaded ASAP, the other is IDE dependent and the best place
for it is a module. But if this will cause problems, I can hapilly
stay with the current solution (keeping in mind, that ideally nothing
should be changed in/copied to ${netbeans.home}/ when running XTest
tests).

#4.1 - so if I create my own URLClassloader, which will be
reposonsible for loading tests and testing libraries (e.g. JUnit,
Jemmy, Jelly), will I see all the necessary stuff from the test
classes and testing libraries (openide/core, public API of installed
modules)? Just one more thing, what about security policy - will I be
able to load tests from somewhere else than from ${netbeans.home} or
will I need to switch off the netbeans security? Also by which
classloader the custom classloader should be loaded ? I suppose it
will have to be in lib/, right?

#4.2 in the case of accessing package private stuff from ordinary
modules, I don't see any problem. These tests just must not use
anything like Jemmy or Jelly and IMHO this is fair assumption
(functional test shoudn't never access package private stuff).

#4.3 I'm not sure if the netbeans.patches.code.name.bese property
works also for openide and core. Does it really work for core classes
loaded by org.netbeans.JarClassLoader?  How should the
netbeans.patches... property look like in this case?
Comment 4 Jesse Glick 2003-01-09 00:05:11 UTC
Re. #1 - users would normally put these things in lib/ext/, I *think*
- not sure what the current status is. (Depends on how JRE classes
find user-supplied classes: simple Class.forName, using a specific
ClassLoader, using Thread.contextClassLoader, etc.)

Re. #2 - would have to be in classpath (lib/ext/), unless the property
contained not only a class name but also a classpath, or was given as
a JAR file with Main-Class, etc.

Re. #3 - not sure what you should do exactly, but I don't think you
need anything from core. Generic init stuff can go into the startup
hook. All else should probably be done when tests are first run?
meaning part of some test infra module, I guess.
ModuleInstall.restored() could be used if you cannot do it on demand
for some reason. If it has soft dependencies on other modules,
consider using eager modules to factor out the dependencies, or you
may prefer to use reflection on the system class loader to access any
module class.

Re. #4.1 - make a URLCL parented to the NB system class loader, then
it access any public or protected class or member in openide, core, or
any module. Re. security policy, give it full permissions (see e.g.
core/src/org/netbeans/core/modules/Module.java for an example, it is
easy). Re. "by which class loader it should be loaded", I don't think
I understand the question. The custom CL is not "loaded" by anything,
it is created by some code you supply, which might live anywhere -
hopefully in a module.

Re. #4.2 - as you like.

Re. #4.3 - currently you can use the netbeans.classpath property to
insert things into the loader used by openide & core.
Comment 5 Martin Brehovsky 2003-01-09 15:15:33 UTC
Re: #1 and #2 - and here comes the original request. I would like
XTest not to change anything in ${netbeans.home} directory during
testing (well, at least when running in a standard mode), so my idea
is to copy all the required stuff rather to ${netbeans.userdir}, since
XTest normally runs netbeans IDE with a clean userdir every time IDE
is started. So do you think it would be possible to make netbeans
check for ${netbeans.userdir}/lib and ${netbeans.userdir}/lib/ext for
mentioned jars?


Re #3 - when IDE is initialized, I just need to prepare IDE for
testing process (e.g. mount necessary jars user  specifies, or in the
future open specifed project if projects are available, etc ...) and
then start the tests. Anyway I'll try the things you suggested. Just
one more question - when ModuleInstall.restored() is called, after all
modules are initialized or immediately my module is loaded? In XTest I
think I need to wait until the whole IDE is initialized before I start
the additional setup and testing process. 

#4.1 - well, I'm not a classloader expert, but the classloader class
has to be loaded by another classloader to be present in VM, right? So
I thought it matters by which classloader is loaded, because the
loading classloader might restrict access rights of the loaded
permissions (or not)? Anyway I'll try to experiment with it a bit to
get more familiar with the classloader magic :-).

Re #4.3 - OK, when the classes specified in this property are loaded?
Before openide/core stuff or after ? (I mean can it be used for
patching ?)
Comment 6 Jesse Glick 2003-01-09 20:33:29 UTC
Re. #1: "So do you think it would be possible to make netbeans check
for ${netbeans.userdir}/lib and ${netbeans.userdir}/lib/ext for
mentioned jars?" - I don't think this is a good idea. It seems to me
that the scope of what this XTest "module" does is getting pretty
confused. Just because you install a test suite does not mean it
should dump all kinds of JDBC drivers into your classpath. The user
should have the option to create a new IDE installation just for
testing - *not* their own installation - with some set of drivers etc.
If this is unacceptable, force the test tools NBM to be installed in
netbeans.home. It is not a "real" module anyway, I don't think anyone
would care.

Re. #3 - "when ModuleInstall.restored() is called, after all modules
are initialized or immediately my module is loaded?" - when your
module is loaded. "I need to wait until the whole IDE is initialized
before I start the additional setup and testing process" - fine,
though what precisely you mean by "initialized" is the hard part.

Re. #4.1 - "the loading classloader might restrict access rights of
the loaded permissions" - I think you are getting confused a bit. The
custom class loader defines permissions for all code loaded from it,
and has full authority for this. To *make* the custom class loader you
need to run some code which will need permissions to create class
loaders, create permission collections, etc. etc. Fortunately all
module code is always given AllPermissions so it can do anything it
likes. I presume the custom class loader would be created from some
module.

Re. #4.3 & "netbeans.classpath" - "when the classes specified in this
property are loaded? Before openide/core stuff or after ?" - before,
of course. The property is consulted when creating the class loader
which will load core.jar and openide.jar. This "classpath" is
prepended, so things in it can override core/openide classes if you
need to do that.
Comment 7 Jesse Glick 2003-01-10 01:10:04 UTC
Re. #4.3 - my mistake, you can in fact still use lib/patches/ for
patching core.jar and openide.jar. But you may prefer to use
netbeans.classpath to avoid modifying the installation.
Comment 8 Martin Brehovsky 2003-01-10 14:36:52 UTC
Re. #1: OK, now when users are not supposed to copy drivers and othe
3rd party libraries to lib/ext, XTest does not have to copy anything
in ${netbeans.home} - I just need to disable this option in the
buildscripts.  The static initialization method for getting IDE PID
can be loaded from a jar specified via -cp:a setting (the jar, if I
understand it correctly, can be stored outside netbeans.home), the
rest of the XTest classes required for running tests in IDE can  be
loaded as a XTest module, which creates it's own classloader to load
tests, runs the testing process and when done it exits IDE in a nice way.

Re. #1 to explain "It seems to me that the scope of what this XTest
"module" does is getting pretty confused" - no, it's not. XTest is not
going yo be just an IDE module. XTest as a module for IDE will be just
a couple of classes reponsible for the stuff written above. But I
still need something, which prepares testing environment for test
execution (e.g. add JDBC drivers to the place where IDE expects them,
the same thing applies to JNDI providers, and more 3rd party stuff not
being distrbuted with IDE). This is also XTest, but not a module part
of it. Furthermore, in the setup part (before running tests) I need to
ensure I don't add/change anything in ${netbeans.home} for let's say
testbag1, which might negatively affect testbag2, which is so
unfortunate to being running just after testbag1. So I thought I could
solve this by copying the stuff to userdir (which is usually  created
everytime new, when IDE is started ->  each testbag has it's own
userdir). It also helps test developers to use IDE from the same
directory for test development as well as for test execution (2 IDEs
are running at the same time) - something, which I was asked for many
times.

Re. #3: by "fully initialized" I mean state, when all visual
components are properly displayed, AWT queue is empty and IDE is ready
for user's input. I'm afraid I'm not able to reliably detect such a
state from ModuleInstall.restored() method (or am I?). On the other
hand, am I able to detect such a state in IDE at all (even is
openide/core able to do that)? 

Re. #4.1 - OK, thanks for explanation, now it's clear.

Re. #4.3 - OK, will implement this using netbeans.classpath


Comment 9 Martin Brehovsky 2003-01-10 15:34:23 UTC
Well, after discussion with Radko, it looks like I'm going to have
item #5:

It doesn't seem to me there exist any standardized way how to add 3rd
party libraries (JDBC, JNDI, CORBA, ...) to IDE. Previously,
everything added to lib/ext could be used as these drivers, providers,
orbs, .... This was quite easy and XTest was able to prepare testing
enviroment with these 3rd party libraries with almost no effort.
Unfortunately, it looks like this is going to change ineavitably, but
I'm afraid there does not exist any standard way (either from the user
point of view or openide API) how to add the libraries. Unfortunately
this can make XTest's test setup process very complicated, because for
every module using 3rd party libaries it would have to support the
module's own way  of adding the libraries -> something which I'm not
interested in implementing in XTest :-(. 

So what I want is that I'd like to see a public openide API, which
would be be implemented by modules like db explorer, and which could
be used by XTest to install the libraries. Do you think something like
this is possible?
Comment 10 Jaroslav Tulach 2004-07-29 09:15:10 UTC
One can always use nbexec -cp:a to append anything to the classpath.
This is a standard API of the launcher. I hope it satisfies your
requirements.
Comment 11 Martin Brehovsky 2004-07-29 11:47:25 UTC
Adding Jirka Skrivanek to CC, because he is currently the owner of XTest.
Comment 12 Jesse Glick 2004-07-29 21:32:37 UTC
Yarda was responding only to #5, not #1-4.
Comment 13 Jiri Skrivanek 2004-08-03 09:52:28 UTC
Martin Brehovsky redesigned XTest that all requested features are now
available. I think this issue can be closed.