/*
 * Jicofo, the Jitsi Conference Focus.
 *
 * Copyright @ 2015 Atlassian Pty Ltd
 *
 * 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 org.jitsi.jicofo;

import mock.*;
import mock.jvb.*;
import mock.util.*;
import mock.xmpp.*;

import net.java.sip.communicator.util.*;

import org.jitsi.eventadmin.*;
import org.jitsi.jicofo.discovery.*;
import org.jitsi.jicofo.event.*;

import org.junit.*;
import org.junit.runner.*;
import org.junit.runners.*;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import static org.mockito.Mockito.*;

/**
 * Tests for {@link JvbDoctor} class.
 *
 * @author Pawel Domas
 */
@RunWith(JUnit4.class)
public class JvbDoctorTest
{
    static OSGiHandler osgi = OSGiHandler.getInstance();

    private static final int HEALTH_CHECK_INT = 300;

    @BeforeClass
    public static void setUpClass()
        throws Exception
    {
        System.setProperty(
            JvbDoctor.HEALTH_CHECK_INTERVAL_PNAME, "" + HEALTH_CHECK_INT);

        osgi.init();
    }

    @AfterClass
    public static void tearDownClass()
        throws Exception
    {
        osgi.shutdown();
    }

    /**
     * The role of <tt>JvbDoctor</tt> is to schedule health-check task for each
     * new bridge discovered and advertised with {@link BridgeEvent#BRIDGE_UP}
     * event. Then a health-check failure should trigger
     * {@link BridgeEvent#HEALTH_CHECK_FAILED} event which after processed by
     * the {@link BridgeSelector} should result in
     * {@link BridgeEvent#BRIDGE_DOWN}. The last event is handled by all
     * {@link JitsiMeetConference} which will restart if are found to be using
     * faulty bridge.
     *
     */
    @Test
    public void jvbDoctorTest()
        throws Exception
    {
        String jvb1 = "jvb1.jitsi.net";

        FocusManager focusManager
            = ServiceUtils.getService(osgi.bc, FocusManager.class);

        assertNotNull(focusManager);

        MockProtocolProvider focusPps
            = (MockProtocolProvider) focusManager.getProtocolProvider();

        assertNotNull(focusPps);

        MockVideobridge mockBridge
            = new MockVideobridge(focusPps.getMockXmppConnection(), jvb1);

        // Make sure that jvb advertises health-check support
        MockSetSimpleCapsOpSet mockCaps = focusPps.getMockCapsOpSet();
        MockCapsNode jvbNode
            = new MockCapsNode(
                    jvb1,
                    new String[] { DiscoveryUtil.FEATURE_HEALTH_CHECK });
        mockCaps.addChildNode(jvbNode);

        // Make mock JVB return error response to health-check IQ
        mockBridge.setReturnHealthError(true);

        mockBridge.start(osgi.bc);

        JitsiMeetServices meetServices
            = ServiceUtils.getService(osgi.bc, JitsiMeetServices.class);

        EventHandler eventSpy = mock(EventHandler.class);
        EventUtil.registerEventHandler(
            osgi.bc,
            new String[] {
                BridgeEvent.BRIDGE_UP,
                BridgeEvent.BRIDGE_DOWN,
                BridgeEvent.HEALTH_CHECK_FAILED },
            eventSpy);

        BridgeSelector selector = meetServices.getBridgeSelector();
        selector.addJvbAddress(jvb1);

        // Verify that BridgeSelector has triggered bridge up event
        verify(eventSpy, timeout(100))
            .handleEvent(BridgeEvent.createBridgeUp(jvb1));

        TestConference[] testConfs = new TestConference[5];
        String roomName = "testHealth@conference.pawel.jitsi.net";
        String serverName = "test-server";

        for (int i=0; i<testConfs.length; i++)
        {
            testConfs[i] = TestConference.allocate(
                osgi.bc, roomName + i, serverName, mockBridge);

            testConfs[i].addParticipant();
            testConfs[i].addParticipant();
        }

        for (TestConference testConf1 : testConfs)
        {
            assertNotNull(
                focusManager.getConference(testConf1.getRoomName()));
        }

        // Here we verify that first there was HEALTH_CHECK_FAILED event
        // send by JvbDoctor
        verify(eventSpy, timeout(HEALTH_CHECK_INT + 100))
            .handleEvent(BridgeEvent.createHealthFailed(jvb1));
        // and after that BRIDGE_DOWN should be triggered
        // by BridgeSelector
        verify(eventSpy, timeout(100))
            .handleEvent(BridgeEvent.createBridgeDown(jvb1));

        // Make sure conferences are now terminated, since we have no secondary
        // bridge
        // FIXME with ICE-restart conference is not destroyed, we should make
        // sure here that it is restarted on a new bridge instead
        //for (TestConference testConf : testConfs)
        //{
        //    assertNull(
        //        focusManager.getConference(testConf.getRoomName()));
        //}

        mockBridge.stop(osgi.bc);
    }
}

@@ -4191,16 +4191,28 @@
 sgi.bc, 
+serverName, 
 roomName
@@ -4215,28 +4215,16 @@
 Name + i
-, serverName
 , mockBr
@@ -4925,168 +4925,60 @@
  // 
-Make sure conferences are now terminated, since we have no secondary%0A        // bridge%0A        // FIXME with ICE-restart conference is not destroyed, we
+We have no secondary bridge, so all restarts
  should 
 make
@@ -4977,12 +4977,12 @@
 uld 
-make
+fail
 %0A   
@@ -4993,47 +4993,66 @@
  // 
-sure here that it is restarted on a new
+We'll know that by having null returned for currently used
  bri
@@ -5061,13 +5061,8 @@
 e in
-stead
 %0A   
@@ -5068,16 +5068,40 @@
       //
+ the conference%0A        
 for (Tes
@@ -5142,18 +5142,16 @@
         
-//
 %7B%0A      
@@ -5156,25 +5156,42 @@
     
-//
     
-assertNull(
+JitsiMeetConference conference
 %0A   
@@ -5199,17 +5199,17 @@
     
-//
+ 
        
+=
  foc
@@ -5255,27 +5255,68 @@
 mName())
+;%0A%0A            assertNotNull(conference
 );%0A
+%0A 
         
 //%7D%0A%0A   
@@ -5307,18 +5307,132 @@
         
-//
+   // No jvb currently in use%0A            assertNull(testConf.getConferenceUtility().getJvbConferenceId());%0A        
 %7D%0A%0A     

Fix JvbDoctorTest