[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
RE: [wtp-dev] JUnit tip: How to delete projects
|
Take a look at org.eclipse.wst.common.tests.ProjectUtility
in the org.eclipse.wst.common.tests plugin. There is a method in
there for deleting projects as well.
Thank you,
Jason A. Sholl
jsholl@xxxxxxxxxx
919-543-0011 (t/l 441-0011)
"Mitov, Kiril"
<k.mitov@xxxxxxx>
Sent by: wtp-dev-bounces@xxxxxxxxxxx
02/01/2008 07:47 AM
Please respond to
"General discussion of project-wide or architectural issues."
<wtp-dev@xxxxxxxxxxx> |
|
To
| "General discussion of project-wide
or architectural issues." <wtp-dev@xxxxxxxxxxx>
|
cc
|
|
Subject
| RE: [wtp-dev] JUnit tip: How to delete
projects |
|
When it comes to deleting files
I have once implemented this method
private
void
deleteFileAndUpdate(IFile file) throws
Exception {
ChangeListenerWithSemaphore listener = new
ChangeListenerWithSemaphore(1);
ResourcesPlugin.getWorkspace().addResourceChangeListener(listener,
IResourceChangeEvent.POST_CHANGE);
int
retries = 3;
while
(retries > 0) {
try
{
deleteFile(file);
if
(listener.waitForEvents()) {
retries
= 0;
break;
}
} catch
(CoreException e) {
... more core here... see in
the description.
} finally
{
retries--;
}
}
assertTrue(retries == -1);
ResourcesPlugin.getWorkspace().removeResourceChangeListener(listener);
}
The basic idea here is that you have
not deleted a file/folder/project until you receive a ResourceChangeEvent
for the deletion.
Since the event might be in the same
thread or in another thread it is important to stop the current
thread until an event occurs. This is what I am doing here. This has also
worked for folders and projects. The listener.waitForEvents() is
blocking the current thread until a notification for the deletion is received.
In general the thread is blocked until the specified number of events
(the number in the constructor of ChangeListenerWithSemaphore) is reached.
But this can easily be changed to an another logic.
Here the "retires" are the
number of failiers that I am willing to accept. In the catch(CoreException
e) there is a special logic. If the message of the exception is "The
requested operation cannot be performed on a file with a user-mapped section
open" the code of the catch block is:
/*
*
An exception was occurring - "The requested operation cannot
*
be performed on a file with a user-mapped section open".
*
Running the finalization as suggested at
*
http://webteam.archive.org/jira/browse/HER-661?decorator=printable
*/
System.runFinalization();
System.gc();
But I was unable to investigate the error
more deeply.
The deleteFile method is:
protected
static
boolean
deleteFile(final
IFile file) throws
Exception {
ResourcesPlugin.getWorkspace().run(new
IWorkspaceRunnable() {
public
void
run(IProgressMonitor monitor) throws
CoreException {
file.delete(false,
monitor);
}
}, monitor);
return
true;
}
The code of ChangeListenerWithSemaphore
is
/**
*
This
change
listener
will
release
a
semaphore
after
the
resource
changed
*
method
is
called.
For
every
resourceChanged
call
one
release
will
be
called.
*
*
@author
Kiril
Mitov
k.mitov@xxxxxxx
*
*/
public
final
class
ChangeListenerWithSemaphore implements
IResourceChangeListener {
private
final
Semaphore s;
private
final
List<Object> deltas;
private
final
int
expectedEvents;
private
final
List<IResourceChangeEvent> receivedEvents;
public
ChangeListenerWithSemaphore(int
expectedEvents) throws
InterruptedException {
this.expectedEvents
= expectedEvents;
this.s
= new
Semaphore(1);
this.s.acquire();
this.deltas
= Collections.synchronizedList(new
LinkedList<Object>());
this.receivedEvents
= Collections.synchronizedList(new
LinkedList<IResourceChangeEvent>());
}
public
synchronized
void
resourceChanged(IResourceChangeEvent event) {
receivedEvents.add(event);
if
(receivedEvents.size()
> expectedEvents)
throw
new
IllegalStateException("The
expected events were already reached");
try
{
deltas.add(event.getDelta());
} catch
(Exception e) {
Activator.getDefault().getLog().log(new
Status(IStatus.ERROR,
Activator.PLUGIN_ID,
e.getMessage(), e));
return;
} finally
{
if
(expectedEvents
== receivedEvents.size())
s.release();
}
}
public
boolean
waitForEvents() throws
InterruptedException {
return
s.tryAcquire(5,
TimeUnit.SECONDS);
}
public
synchronized
List<Object> getDeltas() {
return
deltas;
}
public
synchronized
int
getEvents() {
return
receivedEvents.size();
}
public
List<IResourceChangeEvent> getReceivedEvents() {
return
receivedEvents;
}
}
This is how I am creating, deleting
and updating files.
Best Regards,
Kiril
From: wtp-dev-bounces@xxxxxxxxxxx
[mailto:wtp-dev-bounces@xxxxxxxxxxx] On Behalf Of David M Williams
Sent: Friday, 1. February 2008 10:16
To: wtp-dev@xxxxxxxxxxx
Subject: [wtp-dev] JUnit tip: How to delete projects
Some of our JUnits suites require that projects or other resources be deleted
during the test, for various reasons, and I think some of the "random
errors" we see are because it's hard to delete a project, or file,
in a multi-threaded Eclipse. If there is a file from the project open in
another thread, for example, perhaps in a thread that's running validation,
hence reading files, the delete will fail ("randomly") and then
that might cause a JUnit test to fail, directly or indirectly (by having
an unexpected state).
I had to solve this, just this evening, and took me a while, reading platform
test examples, and googling around, to find a solution that I think is
fairly good ... for JUnit tests, at least.
I've pasted the code below ... just in case it helps anyone. Hopefully
the constants are obvious, but if anyone wants to see the whole class,
it is
org.eclipse.jst.jsp.core.tests.taglibindex.TestIndex
And ... as always the case in open development ... if anyone has other
tips/tricks, or better ways, feel free to let us know.
Thanks,
/**
*
It's not
easy to
delete projects.
If any
of it's
files are
open by
another thread,
*
the operation
will fail.
So, this
method will
make several
attempts before
giving up.
*
@param project
*
@throws CoreException
*
@throws InterruptedException
*/
private
void deleteProject(IProject
project) throws
CoreException, InterruptedException {
int
nTrys = 0;
while
(project != null
&& project.exists() && nTrys < MAX_RETRYS)
{
try
{
nTrys++;
project.delete(true,
true, null);
}
catch
(ResourceException e) {
if
(DEBUG) {
System.out.println();
System.out.println("Could
not delete project on attempt number: "+ nTrys);
IStatus
eStatus = e.getStatus();
//
should always be MultiStatus, but we'll check
if
(eStatus instanceof
MultiStatus) {
MultiStatus mStatus = (MultiStatus) eStatus;
IStatus[] iStatus = mStatus.getChildren();
for
(int j = 0;
j < iStatus.length;
j++) {
System.out.println("Status:
" + j + "
" + iStatus[j]);
}
}
else
{
System.out.println("Status:
" + eStatus);
}
}
/*
* If we could not delete the
first time, wait a bit and
* re-try. If we could not delete,
it is likely because
* another thread has a file open,
or similar (such as the
* validation thread).
*/
Thread.sleep(PAUSE_TIME);
}
}
if
(project != null
&& project.exists()) {
fail("Error
in test infrastructure. Could not delete project "
+ project + " after "
+ MAX_RETRYS + "attempts.");
}
}_______________________________________________
wtp-dev mailing list
wtp-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/wtp-dev