// $Id$
// 
// 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.
// 
using System;
using System.Threading;
using NUnit.Framework;

namespace Org.Apache.Etch.Bindings.Csharp.Util
{
    internal delegate void run();
    
    [TestFixture]
    public class TestCircularQueue
    {

        [TestFixtureSetUp]
        public void First()
        {
            Console.WriteLine();
            Console.Write("TestCircularQueue");
        }

        
        [Test]
       [ExpectedException( typeof( ArgumentOutOfRangeException ) )]
	    public void construct1() 
	    {
		    new CircularQueue<int?>( 0 );
	    }

        
	[Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
	public void construct2() 
	{
		new CircularQueue<int?>( -1 );
	}
	
	
	[Test]
	public void construct3() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
		Assert.AreEqual( 1, queue.Size() );
	}
	
	
	[Test]
	public void construct4() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>( 2 );
		Assert.AreEqual( 2, queue.Size() );
	}
	
	
	[Test]
	public void construct5() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();
		Assert.AreEqual( 10, queue.Size() );
	}
	
	
	[Test]
	public void putget1() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();
		
		Assert.AreEqual( 0, queue.Count() );
		Assert.IsTrue( queue.IsEmpty() );
		Assert.IsFalse( queue.IsFull() );
		
		for (int i = 0; i < 10000; i++)
		{
			queue.Put( i );
			Assert.AreEqual( 1, queue.Count() );
			Assert.IsFalse( queue.IsEmpty() );
			
			Assert.AreEqual( i, queue.Get() );
			Assert.AreEqual( 0, queue.Count() );
			Assert.IsTrue( queue.IsEmpty() );
		}
	}
	
	
	[Test]
	public void putget2() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();
		
		Assert.IsNull( queue.Get( 1 ) );
		Assert.IsNull( queue.Get( -1 ) );
		Assert.IsNull( queue.Get( 10 ) );
		
		queue.Put( 9 );
		Assert.AreEqual( 9, queue.Get( 1 ) );
		
		queue.Put( 9 );
		Assert.AreEqual( 9, queue.Get( -1 ) );
		
		queue.Put( 9 );
		Assert.AreEqual( 9, queue.Get( 10 ) );
		
		Assert.IsNull( queue.Get( 1 ) );
		Assert.IsNull( queue.Get( -1 ) );
		Assert.IsNull( queue.Get( 10 ) );
		
	/*	long t0;
		double t;
		
	
	    t0 = HPTimer.Now();
	    Assert.IsNull(queue.Get(10));
        t = ( HPTimer.Now() - t0) / 1000000.0;
		assertRelError( 10, t, 1 );
		
		
        t0 = HPTimer.Now();
	    Assert.IsNull(queue.Get(20));
        t = (HPTimer.Now() - t0) / 1000000.0;
		assertRelError( 20, t, 1 );
		
	
        t0 = HPTimer.Now();
		Assert.IsNull( queue.Get( 30 ) );
        t = (HPTimer.Now() - t0) / 1000000.0;
		assertRelError( 30, t, 1 ); */
	}
	
	
	[Test]
	public void putget3() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();
		
		Assert.IsTrue( queue.Put( 1 ) );
		Assert.IsTrue( queue.Put( 2 ) );
		Assert.IsTrue( queue.Put( 3 ) );
		Assert.AreEqual( 1, queue.Get() );
		Assert.AreEqual( 2, queue.Get() );
		Assert.AreEqual( 3, queue.Get() );
		
		Assert.IsTrue( queue.Put( 1, 0 ) );
		Assert.IsTrue( queue.Put( 2, 0 ) );
		Assert.IsTrue( queue.Put( 3, 0 ) );
		Assert.AreEqual( 1, queue.Get( 0 ) );
		Assert.AreEqual( 2, queue.Get( 0 ) );
		Assert.AreEqual( 3, queue.Get( 0 ) );
		
		Assert.IsTrue( queue.Put( 1, -1 ) );
		Assert.IsTrue( queue.Put( 2, -1 ) );
		Assert.IsTrue( queue.Put( 3, -1 ) );
		Assert.AreEqual( 1, queue.Get( -1 ) );
		Assert.AreEqual( 2, queue.Get( -1 ) );
		Assert.AreEqual( 3, queue.Get( -1 ) );
		
		Assert.IsTrue( queue.Put( 1, 1 ) );
		Assert.IsTrue( queue.Put( 2, 1 ) );
		Assert.IsTrue( queue.Put( 3, 1 ) );
		Assert.AreEqual( 1, queue.Get( 1 ) );
		Assert.AreEqual( 2, queue.Get( 1 ) );
		Assert.AreEqual( 3, queue.Get( 1 ) );
	}
	
	
	[Test]
	public void get() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
		
	//	System.nanoTime();
        HPTimer.Now();
		Assert.IsNull( queue.Get( 10 ) );
		assertRelError( 1, 1, 1 );

	    foreach (int i in new int[] { 10, 20, 30, 50, 80, 130, 210, 340, 550, 890, 1440 })	   
		{
		//	Console.WriteLine( "get delay = {0}\n", i );
            long t0 = HPTimer.Now();
			Assert.IsNull( queue.Get( i ) );
      /*      double t = (HPTimer.Now() - t0) / 1000000.0;
			assertRelError( i, t, 2 ); */
		}
	}
	
	
	[Test]
        [ExpectedException(typeof(ArgumentNullException))]
	public void put() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();
		queue.Put( null );
	}
	
	
	[Test]
	public void full() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
		
		Assert.IsFalse( queue.IsFull() );
		Assert.IsTrue( queue.Put( 0 ) );
		Assert.IsTrue( queue.IsFull() );
		Assert.AreEqual( 0, queue.Get() );
		Assert.IsFalse( queue.IsFull() );
		
		Assert.IsTrue( queue.Put( 0 ) );
		Assert.IsFalse( queue.Put( 0, -1 ) );
		Assert.IsFalse( queue.Put( 0, 1 ) );
		Assert.IsFalse( queue.Put( 0, 10 ) );
	}
	
	
	[Test]
	public void close1() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();
		
		Assert.IsFalse( queue.IsClosed() );
		queue.Close();
		Assert.IsTrue( queue.IsClosed() );
		
		Assert.IsNull( queue.Get() );
		Assert.IsNull( queue.Get( -1 ) );
		Assert.IsNull( queue.Get( 0 ) );
		Assert.IsNull( queue.Get( 1 ) );
		
		queue.Close();
		Assert.IsTrue( queue.IsClosed() );
	}
	
	
	[Test]
	public void close2() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();

		Assert.IsFalse( queue.IsClosed() );
		queue.Close();
		Assert.IsTrue( queue.IsClosed() );
		
		Assert.IsFalse( queue.Put( 0 ) );
		Assert.IsFalse( queue.Put( 0, -1 ) );
		Assert.IsFalse( queue.Put( 0, 0 ) );
		Assert.IsFalse( queue.Put( 0, 1 ) );
		
		queue.Close();
		Assert.IsTrue( queue.IsClosed() );
	}
	
	
	[Test]
	public void close3() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();
		queue.Put( 1 );
		queue.Put( 2 );
		queue.Put( 3 );
		queue.Close();
		Assert.AreEqual( 1, queue.Get() );
		Assert.AreEqual( 2, queue.Get() );
		Assert.AreEqual( 3, queue.Get() );
		Assert.IsNull( queue.Get() );
	}
	
	
	[Test]
	public void delay1() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>();
		
		Delay( 10, delegate() {queue.Put( 99 ); } );
		Assert.AreEqual( 99, queue.Get() );
		
		Delay( 10, delegate() { queue.Close(); } );
		Assert.IsNull( queue.Get() ); 
	}
	
	
	[Test]
	public void delay2() 
	{
		 CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
		
		Assert.IsTrue( queue.Put( 1 ) );
		Delay( 10, delegate() { Assert.AreEqual( 1, queue.Get() ); } );
		Assert.IsTrue( queue.Put( 2 ) );
		Assert.AreEqual( 2, queue.Get() );
		
		Assert.IsTrue( queue.Put( 1 ) );
	    Delay(10, delegate() { queue.Close(); });
		Assert.IsFalse( queue.Put( 2 ) );
		Assert.AreEqual( 1, queue.Get() );
		Assert.IsNull( queue.Get() );
	}
	
	
	[Test]
	public void stress1() 
	{
		 CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
		 int n = 10000;

         Thread t = new Thread(
             delegate()
             {
                for (int i = 0; i < n; i++)
				{
					try
					{
						queue.Put( i );
					}
					catch ( ThreadInterruptedException e )
					{
						Console.WriteLine(e);
					}
				}  
             }
        );
		
		t.Start();
		
		for (int i = 0; i < n; i++)
			Assert.AreEqual( i, queue.Get() );
	}
	
	
	[Test]
	public void stress2() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
		 int n = 1000;

         Thread t = new Thread(
             delegate()
             {
                for (int i = 0; i < n; i++)
				{
					try
					{
						Thread.Sleep( 5 );
                        queue.Put( i );
					}
					catch ( ThreadInterruptedException e )
					{
						Console.WriteLine(e);
					}
				}  
             }
        );
		
		t.Start();
     
		for (int i = 0; i < n; i++)
			Assert.AreEqual( i, queue.Get() );
	}
	
	
	[Test]
	public void stress3() 
	{
		
        CircularQueue<int?> queue = new CircularQueue<int?>( 1 );
		 int n = 1000;

         Thread t = new Thread(
             delegate()
             {
                for (int i = 0; i < n; i++)
				{
					try
					{
						
                        queue.Put( i );
					}
					catch ( ThreadInterruptedException e )
					{
						Console.WriteLine(e);
					}
				}  
             }
        );
		
		t.Start();
        
        
		
		for (int i = 0; i < n; i++)
		{
			Thread.Sleep( 5 );
			Assert.AreEqual( i, queue.Get() );
		}
	}
	
	
	[Test]
	public void stress4() 
	{
		 CircularQueue<int?> queue = new CircularQueue<int?>();
		
		// we will setup two threads waiting to get and
		// then in a single synchronized step put two
		// items in the queue. the first thread will be
		// woken to get, and once done the second thread
		// should be woken by the first.
		
		Thread t1 = new Thread( 
            delegate()
		    {			
				try
				{
					Assert.IsNotNull( queue.Get() );
				}
				catch ( ThreadInterruptedException e )
				{
					Console.WriteLine(e);
				}
			}
		);
		
		Thread t2 = new Thread( 
            delegate()
		    {
				try
				{
					Assert.IsNotNull( queue.Get() );
				}
				catch ( ThreadInterruptedException e )
				{
                    Console.WriteLine(e);
				}
		    }
        );

		t1.Start();
		t2.Start();
		
		// wait until both threads are waiting on queue...
		
		Thread.Sleep( 100 );
		
		lock(queue)
		{
			queue.Put( 1 );
			queue.Put( 2 );
		}

		harvest( t1 );
		harvest( t2 );
	}
	
	
	[Test]
	public void stress5() 
	{
		 CircularQueue<int?> queue = new CircularQueue<int?>( 3 );
		
		// we will setup two threads waiting to put to the queue,
		// then in a single synchronized step, read two items from
		// the queue. the first thread will be woken to put, and
		// once done the second thread should be woken by the first.
		
		queue.Put( 0 );
		queue.Put( 1 );
		queue.Put( 2 );
		Assert.IsTrue( queue.IsFull() );
		
		Thread t1 = new Thread( 
            delegate()
		    {
			
				try
				{
					Assert.IsTrue( queue.Put( 3 ) );
				}
				catch ( ThreadInterruptedException e )
				{
                    Console.WriteLine(e);
				}
			}
		 );
		
		Thread t2 = new Thread(
            delegate()
		    {
				try
				{
					Assert.IsTrue( queue.Put( 4 ) );
				}
				catch ( ThreadInterruptedException e )
				{
                    Console.WriteLine(e);
				}
			}
		);
		
		t1.Start();
		t2.Start();
		
		// wait until both threads are waiting on queue...
		
		Thread.Sleep( 100 );
		
		lock(queue)
		{
			Assert.IsNotNull( queue.Get() );
			Assert.IsNotNull( queue.Get() );
		}

		harvest( t1 );
		harvest( t2 );
	}
	
	
	[Test]
	public void stress6() 
	{
		CircularQueue<int?> queue = new CircularQueue<int?>( 5 );
		
		// start two getters and two putters and let 'em duke it out...
		
		Thread t1 = new Thread( 
            delegate()
		    {
				try
				{
					for (int i = 0; i < 100; i++)
						Assert.IsTrue( queue.Put( i ) );
				}
				catch ( ThreadInterruptedException e )
				{
                    Console.WriteLine(e);
				}
			}
		);
		
		Thread t2 = new Thread(
            delegate()
		    {
				try
				{
					for (int i = 0; i < 100; i++)
						Assert.IsTrue( queue.Put( i ) );
				}
				catch ( ThreadInterruptedException e )
				{
                    Console.WriteLine(e);
				}
			}
		);
		
		Thread t3 = new Thread(
            delegate()
		    {
				try
				{
					for (int i = 0; i < 100; i++)
						Assert.IsNotNull( queue.Get() );
				}
				catch ( ThreadInterruptedException e )
				{
                    Console.WriteLine(e);
				}
			}
		);
		
		Thread t4 = new Thread(
            delegate()
		    {
				try
				{
					for (int i = 0; i < 100; i++)
						Assert.IsNotNull( queue.Get() );
				}
				catch ( ThreadInterruptedException e )
				{
                    Console.WriteLine(e);
				}
			}
		);
		
		t1.Start();
		t2.Start();
		t3.Start();
		t4.Start();

		harvest( t1 );
		harvest( t2 );
		harvest( t3 );
		harvest( t4 );
	}
	
	
	[Test]
	public void harvest1() 
	{
		Thread t = new Thread(
            delegate()
            {
            }
        );
		t.Start();
		harvest( t );
	}
	
	
	[Test]
    [ExpectedException( typeof( TimeoutException ) )]
	public void harvest2() 
	{
		Thread t = new Thread( 
            delegate() 
		    {
				try
				{
					Thread.Sleep( 10000 );
				}
				catch ( ThreadInterruptedException e )
				{
                    Console.WriteLine(e);
				}
			}
		);
		t.Start();
		harvest( t );
	} 
	
	private void harvest( Thread t ) 
	{
		t.Join( 1000 );
		if (t.IsAlive)
		{
			t.Interrupt();
			throw new TimeoutException( t.Name+" is stuck" );
		}
	}
	
	
	[Test]
	public void testRelError1() 
	{
		assertRelError( 10, 9, .11 );
		assertRelError( 10, 11, .14 );
		assertRelError( 20, 19, .07 );
		assertRelError( 19, 23, .22 );
	}
	
	
	[Test]
     [ExpectedException( typeof(AssertionException ) )]
	public void testRelError2() 
	{
		assertRelError( 9, 8, .1 );
	}
	
	
	[Test]
    [ExpectedException( typeof(AssertionException ) )]
	public void testRelError3() 
	{
		assertRelError( 9, 10, .1 );
	}
	
	
	[Test]
	public void testAbsError1() 
	{
		AssertAbsError( 11, 15, 4 );
		AssertAbsError( 15, 10, 5 );
		AssertAbsError( 5, 3, 2 );
		AssertAbsError( 4, 7, 3 );
	}
	
	
	[Test]
    [ExpectedException( typeof(AssertionException ) )]
	public void testAbsError2() 
	{
		AssertAbsError( 11, 15, 3 );
	}
	
	
	[Test]
    [ExpectedException(typeof(AssertionException))]
	public void testAbsError3() 
	{
		AssertAbsError( 19, 15, 3 );
	} 
	
	private void Delay(  int delay, run del )
	{

        Thread t = new Thread(delegate()
                                  {
                                      try
                                      {
                                          Thread.Sleep(delay);
                                          del();
                                      }
                                      catch (Exception e)
                                      {
                                          Console.WriteLine(e);
                                      }
                                  });
        t.Start();

      
	}
	
	

	private void assertRelError( double expected, double actual, double error )
	{
		double relError = RelError( expected, actual );
		if (relError > error)
			Assert.Fail( String.Format( "expected: {0} but was: {1} relative error: {2}", expected, actual, relError ) );
	}
	
	private void AssertAbsError( double expected, double actual, double error )
	{
		double absError = AbsError( expected, actual );
		if (absError > error)
           
			Assert.Fail( String.Format( "expected: {0} but was: {1} absolute error: {2}", expected, actual, absError ) );
	}
	
	private double RelError( double expected, double actual )
	{
		return AbsError( expected, actual ) / expected;
	}
	
	private double AbsError( double expected, double actual )
	{
		return Math.Abs( expected - actual );
	}

    }
}
