blob: de8d524df7456b44e3fa8265228afb84ea74b7a6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.coordinator.impl;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.CoordinationException;
import org.osgi.service.coordinator.Participant;
import junit.framework.TestCase;
public class CoordinatorImplTest extends TestCase
{
private CoordinationMgr mgr;
private CoordinatorImpl coordinator;
@Override
protected void setUp() throws Exception
{
super.setUp();
mgr = new CoordinationMgr();
coordinator = new CoordinatorImpl(null, mgr);
}
public void test_createCoordination()
{
final String name = "test";
final Coordination c1 = coordinator.create(name, 0);
assertNotNull(c1);
assertEquals(name, c1.getName());
assertNull(coordinator.peek());
assertNull(c1.getFailure());
assertFalse(c1.isTerminated());
assertTrue(c1.getParticipants().isEmpty());
Exception cause = new Exception();
assertTrue(c1.fail(cause));
assertSame(cause, c1.getFailure());
assertTrue(c1.isTerminated());
assertNull(coordinator.peek());
assertFalse(c1.fail(new Exception()));
try
{
c1.end();
fail("Expected CoordinationException.FAILED on end() after fail()");
}
catch (CoordinationException ce)
{
// expected failed
assertEquals(CoordinationException.FAILED, ce.getType());
}
final Coordination c2 = coordinator.create(name, 0);
assertNotNull(c2);
assertEquals(name, c2.getName());
assertNull(coordinator.peek());
assertNull(c2.getFailure());
assertFalse(c2.isTerminated());
assertTrue(c2.getParticipants().isEmpty());
c2.end();
assertNull(c2.getFailure());
assertTrue(c2.isTerminated());
assertNull(coordinator.peek());
assertFalse(c2.fail(new Exception()));
try
{
c2.end();
fail("Expected CoordinationException.ALREADY_ENDED on second end()");
}
catch (CoordinationException ce)
{
// expected already terminated
assertEquals(CoordinationException.ALREADY_ENDED, ce.getType());
}
}
public void test_beginCoordination()
{
final String name = "test";
final Coordination c1 = coordinator.begin(name, 0);
assertNotNull(c1);
assertEquals(name, c1.getName());
assertEquals(c1, coordinator.peek());
assertEquals(c1, coordinator.pop());
assertNull(coordinator.peek());
c1.push();
assertEquals(c1, coordinator.peek());
c1.end();
assertNull(coordinator.peek());
final Coordination c2 = coordinator.begin(name, 0);
assertNotNull(c2);
assertEquals(name, c2.getName());
assertEquals(c2, coordinator.peek());
c2.fail(new Exception());
assertNotNull(coordinator.peek());
try {
c2.end();
fail("Exception should be thrown");
} catch (CoordinationException ce) {
// ignore
}
assertNull(coordinator.peek());
}
public void test_beginCoordination_stack()
{
final String name = "test";
final Coordination c1 = coordinator.begin(name, 0);
assertNotNull(c1);
assertEquals(name, c1.getName());
assertEquals(c1, coordinator.peek());
final Coordination c2 = coordinator.begin(name, 0);
assertNotNull(c2);
assertEquals(name, c2.getName());
assertEquals(c2, coordinator.peek());
c2.end();
assertEquals(c1, coordinator.peek());
c1.end();
assertNull(coordinator.peek());
}
public void test_beginCoordination_stack2()
{
final String name = "test";
final Coordination c1 = coordinator.begin(name, 0);
assertNotNull(c1);
assertEquals(name, c1.getName());
assertEquals(c1, coordinator.peek());
final Coordination c2 = coordinator.begin(name, 0);
assertNotNull(c2);
assertEquals(name, c2.getName());
assertEquals(c2, coordinator.peek());
c1.end();
assertNull(coordinator.peek());
try
{
c2.end();
fail("c2 is already terminated");
}
catch (CoordinationException ce)
{
assertEquals(CoordinationException.ALREADY_ENDED, ce.getType());
}
assertNull(coordinator.peek());
}
public void test_addParticipant_with_ended()
{
final String name = "test";
final Coordination c1 = coordinator.create(name, 0);
final MockParticipant p1 = new MockParticipant();
c1.addParticipant(p1);
assertTrue(c1.getParticipants().contains(p1));
assertEquals(1, c1.getParticipants().size());
c1.end();
assertTrue(p1.ended);
assertFalse(p1.failed);
assertEquals(c1, p1.c);
// assert order of call
final Coordination c2 = coordinator.create(name, 0);
final MockParticipant p21 = new MockParticipant();
final MockParticipant p22 = new MockParticipant();
c2.addParticipant(p21);
c2.addParticipant(p22);
assertTrue(c2.getParticipants().contains(p21));
assertTrue(c2.getParticipants().contains(p22));
assertEquals(2, c2.getParticipants().size());
c2.end();
assertTrue(p21.ended);
assertEquals(c2, p21.c);
assertTrue(p22.ended);
assertEquals(c2, p22.c);
assertTrue("p22 must be called before p21", p22.time < p21.time);
// assert order of call with two registrations
final Coordination c3 = coordinator.create(name, 0);
final MockParticipant p31 = new MockParticipant();
final MockParticipant p32 = new MockParticipant();
c3.addParticipant(p31);
c3.addParticipant(p32);
c3.addParticipant(p31); // should be "ignored"
assertTrue(c3.getParticipants().contains(p31));
assertTrue(c3.getParticipants().contains(p32));
assertEquals(2, c3.getParticipants().size());
c3.end();
assertTrue(p31.ended);
assertEquals(c3, p31.c);
assertTrue(p32.ended);
assertEquals(c3, p32.c);
assertTrue("p32 must be called before p31", p32.time < p31.time);
}
public void test_addParticipant_with_failed()
{
final String name = "test";
final Coordination c1 = coordinator.create(name, 0);
final MockParticipant p1 = new MockParticipant();
c1.addParticipant(p1);
assertTrue(c1.getParticipants().contains(p1));
assertEquals(1, c1.getParticipants().size());
c1.fail(new Exception());
assertFalse(p1.ended);
assertTrue(p1.failed);
assertEquals(c1, p1.c);
// assert order of call
final Coordination c2 = coordinator.create(name, 0);
final MockParticipant p21 = new MockParticipant();
final MockParticipant p22 = new MockParticipant();
c2.addParticipant(p21);
c2.addParticipant(p22);
assertTrue(c2.getParticipants().contains(p21));
assertTrue(c2.getParticipants().contains(p22));
assertEquals(2, c2.getParticipants().size());
c2.fail(new Exception());
assertTrue(p21.failed);
assertEquals(c2, p21.c);
assertTrue(p22.failed);
assertEquals(c2, p22.c);
assertTrue("p22 must be called before p21", p22.time < p21.time);
// assert order of call with two registrations
final Coordination c3 = coordinator.create(name, 0);
final MockParticipant p31 = new MockParticipant();
final MockParticipant p32 = new MockParticipant();
c3.addParticipant(p31);
c3.addParticipant(p32);
c3.addParticipant(p31); // should be "ignored"
assertTrue(c3.getParticipants().contains(p31));
assertTrue(c3.getParticipants().contains(p32));
assertEquals(2, c3.getParticipants().size());
c3.fail(new Exception());
assertTrue(p31.failed);
assertEquals(c3, p31.c);
assertTrue(p32.failed);
assertEquals(c3, p32.c);
assertTrue("p31 must be called before p32", p32.time < p31.time);
}
public void test_Coordination_timeout() throws InterruptedException
{
final String name = "test";
final Coordination c1 = coordinator.create(name, 200);
final MockParticipant p1 = new MockParticipant();
c1.addParticipant(p1);
assertTrue(c1.getParticipants().contains(p1));
assertEquals(1, c1.getParticipants().size());
// wait for the coordination to time out
Thread.sleep(250);
// expect coordination to have terminated
assertTrue(c1.isTerminated());
assertSame(Coordination.TIMEOUT, c1.getFailure());
// expect Participant.failed() being called
assertTrue(p1.failed);
assertEquals(c1, p1.c);
}
public void test_Coordination_addParticipant_timeout() throws InterruptedException
{
final String name1 = "test1";
final String name2 = "test2";
final MockParticipant p1 = new MockParticipant();
// ensure short timeout for participation
mgr.configure(200);
final Coordination c1 = coordinator.create(name1, 0);
c1.addParticipant(p1);
assertTrue(c1.getParticipants().contains(p1));
assertEquals(1, c1.getParticipants().size());
// preset p1PartFailure to be be sure the participation actually starts
p1.addParticipantFailure(new Exception("Not Started yet"));
Thread c2Thread = new Thread()
{
@Override
public void run()
{
final Coordination c2 = coordinator.create(name2, 0);
try
{
p1.addParticipantFailure(null);
c2.addParticipant(p1);
}
catch (Throwable t)
{
p1.addParticipantFailure(t);
}
finally
{
c2.end();
}
}
};
c2Thread.start();
// wait at most 2 seconds for the second thread to terminate
// we expect this if the participation properly times out
c2Thread.join(2000);
assertFalse("Thread for second Coordination did not terminate....", c2Thread.isAlive());
Throwable p1PartFailure = p1.addParticipantFailure;
if (p1PartFailure == null)
{
fail("Expecting CoordinationException/FAILED for second participation");
}
else if (p1PartFailure instanceof CoordinationException)
{
assertEquals(CoordinationException.FAILED, ((CoordinationException) p1PartFailure).getType());
}
else
{
fail("Unexpected Throwable while trying to addParticipant: " + p1PartFailure);
}
c1.end();
// make sure c2Thread has terminated
if (c2Thread.isAlive())
{
c2Thread.interrupt();
c2Thread.join(1000);
assertFalse("Thread for second Coordination did still not terminate....", c2Thread.isAlive());
}
}
static final class MockParticipant implements Participant
{
long time;
Coordination c;
boolean failed;
boolean ended;
Throwable addParticipantFailure;
public void failed(Coordination c) throws Exception
{
this.failed = true;
this.c = c;
this.time = System.nanoTime();
}
public void ended(Coordination c) throws Exception
{
this.ended = true;
this.c = c;
this.time = System.nanoTime();
}
void addParticipantFailure(Throwable t)
{
this.addParticipantFailure = t;
}
}
}