// 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 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);
    }

}
