// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.network.security;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.cloud.utils.Profiler;

import junit.framework.TestCase;

public class SecurityGroupQueueTest extends TestCase {
    public final static SecurityGroupWorkQueue queue = new LocalSecurityGroupWorkQueue();
  
    
    public static class Producer implements Runnable {
        int _maxVmId = 0;
        int _newWorkQueued=0;
        Set<Long> vmIds = new HashSet<Long>();
        
        public Producer(int maxVmId) {
           this._maxVmId = maxVmId; 
           for (long i=1; i <= _maxVmId; i++) {
               vmIds.add(i);
           }
        }
        
        public void run() {
            _newWorkQueued = queue.submitWorkForVms(vmIds);
        }
        
        public int getNewWork() {
            return _newWorkQueued;
        }
        
        public int getTotalWork() {
            return _maxVmId;
        }
    }
    
    public static class Consumer implements Runnable {
        private int _numJobsToDequeue = 0;
        private int _numJobsDequeued = 0;

        public Consumer(int numJobsToDequeu) {
            this._numJobsToDequeue = numJobsToDequeu;
        }
        
        public void run() {
            List<SecurityGroupWork> result = new ArrayList<SecurityGroupWork>();
            try {
                result = queue.getWork(_numJobsToDequeue);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            this._numJobsDequeued = result.size();
        }
        
        int getNumJobsToDequeue() {
            return _numJobsToDequeue;
        }
        
        int getNumJobsDequeued() {
            return _numJobsDequeued;
        }
    }
    
    public void testNumJobsEqToNumVms1() {
        queue.clear();
        final int numProducers = 50;
        Thread [] pThreads = new Thread[numProducers];
        
        Producer [] producers = new Producer[numProducers];
        int numProduced = 0;

        for (int i=0; i < numProducers; i++) {
            producers[i] = new Producer(i+1);
            pThreads[i] = new Thread(producers[i]);
            numProduced += i+1;
            pThreads[i].start();
        }
        for (int i=0; i < numProducers ; i++) {
            try {
                pThreads[i].join();
            } catch (InterruptedException ie){
                ie.printStackTrace();
            }
        }
        System.out.println("Num Vms= " + numProducers + " Queue size = " + queue.size());
        assertEquals(numProducers, queue.size());
    }
    
    protected void testNumJobsEqToNumVms2(int numProducers, int maxVmId) {
        queue.clear();

        Thread [] pThreads = new Thread[numProducers];
        
        Producer [] producers = new Producer[numProducers];
        int numProduced = 0;
        Profiler p = new Profiler();
        p.start();
        for (int i=0; i < numProducers; i++) {
            producers[i] = new Producer(maxVmId);
            pThreads[i] = new Thread(producers[i]);
            numProduced += i+1;
            pThreads[i].start();
        }
        for (int i=0; i < numProducers ; i++) {
            try {
                pThreads[i].join();
            } catch (InterruptedException ie){
                ie.printStackTrace();
            }
        }
        p.stop();
        System.out.println("Num Vms= " + maxVmId + " Queue size = " + queue.size() + " time=" + p.getDuration() + " ms");
        assertEquals(maxVmId, queue.size());
    }
    
    public  void testNumJobsEqToNumVms3() {
        testNumJobsEqToNumVms2(50,20000);
        testNumJobsEqToNumVms2(400,5000);
        testNumJobsEqToNumVms2(1,1);
        testNumJobsEqToNumVms2(1,1000000);
        testNumJobsEqToNumVms2(1000,1);

    }
    
    protected void _testDequeueOneJob(final int numConsumers, final int numProducers, final int maxVmId) {
        queue.clear();

        Thread [] pThreads = new Thread[numProducers];
        Thread [] cThreads = new Thread[numConsumers];
        
        
        Consumer [] consumers = new Consumer[numConsumers];
        Producer [] producers = new Producer[numProducers];
        
        int numProduced = 0;
        for (int i=0; i < numConsumers; i++) {
            consumers[i] = new Consumer(1);
            cThreads[i] = new Thread(consumers[i]);
            cThreads[i].start();
        }
        for (int i=0; i < numProducers; i++) {
            producers[i] = new Producer(maxVmId);
            pThreads[i] = new Thread(producers[i]);
            numProduced += maxVmId;
            pThreads[i].start();
        }
        for (int i=0; i < numConsumers ; i++) {
            try {
                cThreads[i].join();
            } catch (InterruptedException ie){
                ie.printStackTrace();
            }
        }
        for (int i=0; i < numProducers ; i++) {
            try {
                pThreads[i].join();
            } catch (InterruptedException ie){
                ie.printStackTrace();
            }
        }

        int totalDequeued = 0;
        for (int i=0; i < numConsumers; i++) {
            //System.out.println("Consumer " + i + " ask to dequeue " + consumers[i].getNumJobsToDequeue() + ", dequeued " + consumers[i].getNumJobsDequeued());
            totalDequeued += consumers[i].getNumJobsDequeued();
        }
        int totalQueued = 0;
        for (int i=0; i < numProducers; i++) {
            //System.out.println("Producer " + i + " ask to queue " + producers[i].getTotalWork() + ", queued " + producers[i].getNewWork());
            totalQueued += producers[i].getNewWork();
        }
        System.out.println("Total jobs dequeued = " + totalDequeued + ", num queued=" + totalQueued + " queue current size=" + queue.size());
        assertEquals(totalDequeued, numConsumers);
        assertEquals(totalQueued - totalDequeued, queue.size());
    }
    
    public void testDequeueOneJobAgain() {
        _testDequeueOneJob(10,10,1000);
        int queueSize = queue.size();
        Thread cThread = new Thread(new Consumer(1));
        cThread.start();
        try {
            cThread.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        assertEquals(queue.size(), queueSize-1);
    }
    
    public void testDequeueOneJob() {
        _testDequeueOneJob(10,10,1000);
        _testDequeueOneJob(1,10,1000);
        _testDequeueOneJob(10,1,1000);
        _testDequeueOneJob(10,1,10);
    }

}
