/*
 * Copyright (c) 2015 Inocybe and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.ovsdb.openstack.netvirt.impl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.verifyPrivate;

import java.lang.reflect.Field;
import java.util.Random;
import java.util.concurrent.BlockingQueue;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent;
import org.opendaylight.ovsdb.openstack.netvirt.AbstractHandler;
import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
import org.osgi.framework.ServiceReference;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

/**
 * Unit test for {@link EventDispatcherImpl}
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest({ServiceHelper.class, EventDispatcherImpl.class})
public class EventDispatcherImplTest {

    @InjectMocks private EventDispatcherImpl eventDispatcherImpl;

    @Mock private AbstractHandler handler;
    @Mock private ServiceReference<?> ref;

    private AbstractEvent.HandlerType handlerTypeObject = AbstractEvent.HandlerType.NEUTRON_FLOATING_IP;

    @Before
    public void setUp() {
        Random r = new Random();

        when(ref.getProperty(org.osgi.framework.Constants.SERVICE_ID)).thenReturn(r.nextLong());
        when(ref.getProperty(Constants.EVENT_HANDLER_TYPE_PROPERTY)).thenReturn(handlerTypeObject);
    }

    /**
     * Test methods {@link EventDispatcherImpl#eventHandlerRemoved(ServiceReference)}
     * and {@link EventDispatcherImpl#eventHandlerAdded(ServiceReference, AbstractHandler)}
     */
    @Test
    public void testHandlerAddedAndRemoved() throws Exception{
        AbstractHandler[] handlers = ( AbstractHandler[]) getField("handlers");

        assertNotEquals("Error, handler should be null", handlers[handlerTypeObject.ordinal()], handler);

        eventDispatcherImpl.eventHandlerAdded(ref, handler);

        assertEquals("Error, did not return the added handler", handlers[handlerTypeObject.ordinal()], handler);

        eventDispatcherImpl.eventHandlerRemoved(ref);

        assertNull("Error, handler should be null as it has just been removed", handlers[handlerTypeObject.ordinal()]);
    }

    /**
     * Test method {@link EventDispatcherImpl#enqueueEvent(AbstractEvent)}
     */
    @SuppressWarnings("unchecked")
    @Test
    public void testEnqueueEvent() throws Exception{
        BlockingQueue<AbstractEvent> events = (BlockingQueue<AbstractEvent>) getField("events");

        assertEquals("Error, did not return the expected size, nothing has been added yet", 0, events.size());

        AbstractEvent mockEvent = mock(AbstractEvent.class);
        when(mockEvent.getHandlerType()).thenReturn(handlerTypeObject);
        eventDispatcherImpl.enqueueEvent(mockEvent);
        eventDispatcherImpl.enqueueEvent(mockEvent);
        eventDispatcherImpl.enqueueEvent(mockEvent);
        eventDispatcherImpl.enqueueEvent(mockEvent);

        verifyPrivate(eventDispatcherImpl, times(4)).invoke("dispatchEvent", mockEvent);
    }

    private Object getField(String fieldName) throws Exception {
        Field field = EventDispatcherImpl.class.getDeclaredField(fieldName);
        field.setAccessible(true);
        return field.get(eventDispatcherImpl);
    }
}

@@ -17,16 +17,22 @@
 (c) 2015
+, 2016
  Inocybe
@@ -603,20 +603,22 @@
 Mockito.
-when
+verify
 ;%0Aimport
@@ -633,30 +633,16 @@
 org.
-powermock.api.
 mockito.
 Powe
@@ -641,21 +641,16 @@
 ito.
-Power
 Mockito.
 veri
@@ -645,29 +645,20 @@
 Mockito.
-verifyPrivate
+when
 ;%0A%0Aimpor
@@ -805,98 +805,8 @@
 st;%0A
-import org.junit.runner.RunWith;%0Aimport org.mockito.InjectMocks;%0Aimport org.mockito.Mock;%0A
 impo
@@ -1008,347 +1008,106 @@
 rg.o
-pendaylight.ovsdb.utils.servicehelper.ServiceHelper;%0Aimport org.osgi.framework.ServiceReference;%0Aimport org.powermock.core.classloader.annotations.PrepareForTest;%0Aimport org.powermock.modules.junit4.PowerMockRunner;%0A%0A/**%0A * Unit test for %7B@link EventDispatcherImpl%7D%0A */%0A@RunWith(PowerMockRunner.class)%0A@PrepareForTest(%7BServiceHelper.
+sgi.framework.ServiceReference;%0A%0A/**%0A * Unit test for %7B@link EventDispatcherImpl%7D%0A */%0Apublic 
 class
-,
  Eve
@@ -1126,83 +1126,49 @@
 Impl
-.class%7D)%0Apublic class EventDispatcherImplTest %7B%0A%0A    @InjectMocks private E
+Test %7B%0A%0A    private EventDispatcherImpl e
 vent
@@ -1174,33 +1174,39 @@
 tDispatcherImpl 
-e
+= new E
 ventDispatcherIm
@@ -1211,21 +1211,17 @@
 Impl
+()
 ;%0A%0A    
-@Mock 
 priv
@@ -1251,19 +1251,43 @@
 dler
-;%0A    @Mock
+ = mock(AbstractHandler.class);%0A   
  pri
@@ -1314,16 +1314,47 @@
 e%3C?%3E ref
+ = mock(ServiceReference.class)
 ;%0A%0A    p
@@ -2938,24 +2938,86 @@
 s.size());%0A%0A
+        eventDispatcherImpl.eventHandlerAdded(ref, handler);%0A%0A
         Abst
@@ -3149,290 +3149,534 @@
     
-eventDispatcherImpl.enqueueEvent(mockEvent);%0A        eventDispatcherImpl.enqueueEvent(mockEvent);%0A        eventDispatcherImpl.enqueueEvent(mockEvent);%0A        eventDispatcherImpl.enqueueEvent(mockEvent);%0A%0A        verifyPrivate(eventDispatcherImpl, times(4)).invoke(%22dispatch
+final int numEnqueues = 4;%0A        for (int i = 0; i %3C numEnqueues; i++) %7B%0A            eventDispatcherImpl.enqueueEvent(mockEvent);%0A        %7D%0A%0A        // Because events are processed in a different thread, this is a race%0A        // We want to ensure that all the events were enqueued; so the sum of%0A        // what's been processed and what's still in the queue must equal the%0A        // number of events we enqueued%0A        eventDispatcherImpl.stop();%0A        verify(handler, times(numEnqueues - events.size())).process
 Event
-%22, 
+(
 mock

Rework testEnqueueEvent to avoid private methods