/** * Copyright 2010-2011 Voxeo Corporation * * Licensed 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 com.voxeo.moho.conference; import java.util.Properties; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import javax.media.mscontrol.Configuration; import javax.media.mscontrol.MediaEventListener; import javax.media.mscontrol.MsControlFactory; import javax.media.mscontrol.Parameters; import javax.media.mscontrol.join.Joinable.Direction; import javax.media.mscontrol.networkconnection.NetworkConnection; import javax.sdp.SdpFactory; import javax.servlet.sip.SipFactory; import javax.servlet.sip.SipServlet; import junit.framework.TestCase; import org.hamcrest.Description; import org.jmock.Expectations; import org.jmock.Mockery; import org.jmock.api.Action; import org.jmock.api.Invocation; import org.jmock.lib.legacy.ClassImposteriser; import com.voxeo.moho.Application; import com.voxeo.moho.ApplicationContextImpl; import com.voxeo.moho.Call; import com.voxeo.moho.JointImpl; import com.voxeo.moho.MixerEndpoint; import com.voxeo.moho.Participant; import com.voxeo.moho.Participant.JoinType; import com.voxeo.moho.common.event.MohoHangupEvent; import com.voxeo.moho.event.InputCompleteEvent; import com.voxeo.moho.event.JoinCompleteEvent; import com.voxeo.moho.event.Observer; import com.voxeo.moho.media.Input; import com.voxeo.moho.media.Prompt; import com.voxeo.moho.media.fake.MockMediaMixer; import com.voxeo.moho.media.fake.MockMediaSession; import com.voxeo.moho.media.input.InputCommand; import com.voxeo.moho.media.input.SimpleGrammar; import com.voxeo.moho.media.output.OutputCommand; import com.voxeo.moho.media.output.TextToSpeechResource; import com.voxeo.moho.sip.SIPCallImpl; import com.voxeo.moho.sip.fake.MockSipServlet; import com.voxeo.moho.spi.ExecutionContext; public class ConferenceTest extends TestCase { Mockery mockery = new Mockery() { { setImposteriser(ClassImposteriser.INSTANCE); } }; // JSR309 mock MsControlFactory msFactory = mockery.mock(MsControlFactory.class); MockMediaSession mediaSession = mockery.mock(MockMediaSession.class); MockMediaMixer mixer = mockery.mock(MockMediaMixer.class); // JSR289 mock SipServlet servlet = new MockSipServlet(mockery); // Moho TestApp app = mockery.mock(TestApp.class); // ApplicationContextImpl is simple, no need to mock it. ExecutionContext appContext = null; SipFactory sipFactory = null; SdpFactory sdpFactory = null; MixerEndpoint address; ConferenceImpl mohoConference; Properties props = new Properties(); protected void setUp() throws Exception { super.setUp(); mockery.checking(new Expectations() { { // creation oneOf(msFactory).getProperties(); will(returnValue(props)); } }); if (appContext == null) { appContext = new ApplicationContextImpl(app, msFactory, servlet); sipFactory = appContext.getSipFactory(); sdpFactory = appContext.getSdpFactory(); } address = (MixerEndpoint) appContext.createEndpoint(MixerEndpoint.DEFAULT_MIXER_ENDPOINT); } protected void tearDown() throws Exception { super.tearDown(); appContext.destroy(); } /** * test join and unjoin(); */ public void testConferenceJoinAndUnjoin() { // create conference preparation. try { mockery.checking(new Expectations() { { // creation oneOf(msFactory).createMediaSession(); will(returnValue(mediaSession)); oneOf(mediaSession).createMediaMixer(with(any(Configuration.class)), with(any(Parameters.class))); will(returnValue(mixer)); oneOf(mixer).addListener(with(any(MediaEventListener.class))); will(returnValue(null)); } }); } catch (Exception ex) { ex.printStackTrace(); } final OutputCommand promptCommand = new OutputCommand(new TextToSpeechResource("welcome, password needed.")); final InputCommand passCommand = new InputCommand(new SimpleGrammar("123")); final InputCommand exitCommand = new InputCommand(new SimpleGrammar("1#")); final OutputCommand exitAnnouncement = new OutputCommand(new TextToSpeechResource("bye.")); // create conference. SimpleConferenceController controller = new SimpleConferenceController(promptCommand, passCommand, 3, exitCommand, exitAnnouncement); ConferenceManager manager = new ConferenceMangerImpl(appContext); mohoConference = (ConferenceImpl) manager.createConference(address, null, null, 10, controller, null); // verify the creation result. assertTrue(mohoConference.getMaxSeats() == 10); assertTrue(mohoConference.getOccupiedSeats() == 0); // mock the call final SIPCallImpl call = mockery.mock(SIPCallImpl.class); final NetworkConnection callNet = mockery.mock(NetworkConnection.class); final Prompt<Call> prompt = mockery.mock(Prompt.class); final Input<Call> input = mockery.mock(Input.class); final InputCompleteEvent<Call> event = mockery.mock(InputCompleteEvent.class); final MockMediaMixer multipleJoiningMixer = mockery.mock(MockMediaMixer.class, "callmultipleJoiningMixer"); try { mockery.checking(new Expectations() { { allowing(call).getMediaObject(); will(returnValue(callNet)); oneOf(call).prompt(with(same(promptCommand)), with(same(passCommand)), with(equal(3))); will(returnValue(prompt)); allowing(call).getMultipleJoiningMixer(); will(returnValue(multipleJoiningMixer)); allowing(prompt).getInput(); will(returnValue(input)); allowing(input).get(); will(returnValue(event)); allowing(event).hasMatch(); will(returnValue(true)); allowing(call).getMultipleJoiningMixer(); will(returnValue(multipleJoiningMixer)); allowing(call).getParticipants(); will(returnValue(new Participant[]{})); oneOf(call).addObserver(with(any(Observer.class))); oneOf(call).input(exitCommand); // join oneOf(call).join(mohoConference, JoinType.BRIDGE,false, Direction.DUPLEX); will(new Action() { @Override public void describeTo(Description description) { } @Override public Object invoke(Invocation invocation) throws Throwable { mohoConference.addParticipant(call, JoinType.BRIDGE, Direction.DUPLEX, null); return new JointImpl(new ThreadPoolExecutor(1, 1, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1)), new JointImpl.DummyJoinWorker(mohoConference, call)); } }); // unjoin //oneOf(mixer).unjoin(callNet); oneOf(call).doUnjoin(mohoConference, false); oneOf(call).output(with(same(exitAnnouncement))); oneOf(call).dispatch(with(any(JoinCompleteEvent.class))); } }); } catch (Exception ex) { ex.printStackTrace(); fail(ex.getMessage()); } // execute join. try { mohoConference.join(call, JoinType.BRIDGE, Direction.DUPLEX).get(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } // verify join result. assertTrue(mohoConference.getOccupiedSeats() == 1); assertTrue(mohoConference.getParticipants()[0] == call); // execute unjoin. try { mohoConference.unjoin(call).get(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } // verify unjoin result. assertTrue(mohoConference.getOccupiedSeats() == 0); assertTrue(mohoConference.getParticipants().length == 0); mockery.assertIsSatisfied(); } /** * test password error. */ public void testConferenceJoinFail() { // create conference preparation. try { mockery.checking(new Expectations() { { // creation oneOf(msFactory).createMediaSession(); will(returnValue(mediaSession)); oneOf(mediaSession).createMediaMixer(with(any(Configuration.class)), with(any(Parameters.class))); will(returnValue(mixer)); oneOf(mixer).addListener(with(any(MediaEventListener.class))); will(returnValue(null)); } }); } catch (Exception ex) { ex.printStackTrace(); } final OutputCommand promptCommand = new OutputCommand(new TextToSpeechResource("welcome, password needed.")); final InputCommand passCommand = new InputCommand(new SimpleGrammar("123")); final InputCommand exitCommand = new InputCommand(new SimpleGrammar("1#")); final OutputCommand exitAnnouncement = new OutputCommand(new TextToSpeechResource("bye.")); // create conference. SimpleConferenceController controller = new SimpleConferenceController(promptCommand, passCommand, 3, exitCommand, exitAnnouncement); ConferenceManager manager = new ConferenceMangerImpl(appContext); mohoConference = (ConferenceImpl) manager.createConference(address, null, null, 10, controller, null); // verify the creation result. assertTrue(mohoConference.getMaxSeats() == 10); assertTrue(mohoConference.getOccupiedSeats() == 0); // mock the call final Call call = mockery.mock(Call.class); final NetworkConnection callNet = mockery.mock(NetworkConnection.class); final Prompt<Call> prompt = mockery.mock(Prompt.class); final Input<Call> input = mockery.mock(Input.class); final InputCompleteEvent<Call> event = mockery.mock(InputCompleteEvent.class); try { mockery.checking(new Expectations() { { allowing(call).getMediaObject(); will(returnValue(callNet)); oneOf(call).prompt(with(same(promptCommand)), with(same(passCommand)), with(equal(3))); will(returnValue(prompt)); allowing(prompt).getInput(); will(returnValue(input)); allowing(input).get(); will(returnValue(event)); allowing(event).hasMatch(); will(returnValue(false)); } }); } catch (Exception ex) { ex.printStackTrace(); fail(ex.getMessage()); } // execute join. try { mohoConference.join(call, JoinType.BRIDGE, Direction.DUPLEX).get(); fail("don't catch the excpetion"); } catch (Exception ex) { assertTrue(ex.getCause() instanceof ConferencePasswordNoMatchException); } // verify join result. assertTrue(mohoConference.getOccupiedSeats() == 0); assertTrue(mohoConference.getParticipants().length == 0); mockery.assertIsSatisfied(); } abstract class TestApp implements Application { public abstract void handleDisconnect(MohoHangupEvent event); public final void destroy() { } } }