<|start_filename|>demo/DemoForm.cs<|end_filename|>
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Cyotek.Collections.Generic.CircularBuffer.Demo
{
  public partial class DemoForm : Form
  {
    #region Private Fields

    private Pen _bodyPen;

    private Point[] _buffer;

    private Direction _direction;

    private int _gridSize;

    private Pen _headPen;

    private int _headSize;

    private long _moveCount;

    private Random _random;

    private CircularBuffer<Point> _snakeBody;

    private Point _snakeHead;

    private double _turnChance;

    #endregion Private Fields

    #region Public Constructors

    public DemoForm()
    {
      this.InitializeComponent();
    }

    #endregion Public Constructors

    #region Protected Methods

    protected override void OnLoad(EventArgs e)
    {
      this.DoubleBuffered = true;

      base.OnLoad(e);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
      base.OnPaint(e);

      Graphics g;

      g = e.Graphics;

      g.Clear(Color.FromArgb(255, 255, 220));

      g.SmoothingMode = SmoothingMode.AntiAlias;

      if (_snakeBody.Size > 1)
      {
        // don't do this!
        //g.DrawLines(_bodyPen, _snakeBody.ToArray());

        if (!this.HasSplitResults())
        {
          // this isn't great either really, but as Graphics.DrawLines
          // isn't enlightened enough to take a start and length,
          // we copy the buffer out of the CircularBuffer into an
          // existing byte array so in theory we aren't allocating
          // an array over and over again. In this demo though, we
          // are if the sizes are different
          this.EnsureSize(ref _buffer, _snakeBody.Size);
          _snakeBody.CopyTo(_buffer);

          g.DrawLines(_bodyPen, _buffer);
        }
        else
        {
          int start;
          Point previous;
          Point current;

          // if we've wrapped the playing field, I can't just
          // call DrawLines with the entire buffer as we'll get
          // lines drawn across the entire playing field, so
          // instead I need to break it down into smaller buffers.
          // In this scenario I'd be better off with a pool, but
          // I haven't implemented one for this simple demo

          start = 0;
          previous = _snakeBody.PeekAt(0);

          for (int i = 1; i < _snakeBody.Size; i++)
          {
            current = _snakeBody.PeekAt(i);

            if (this.GetDistance(previous, current) > _gridSize)
            {
              // here we have a split, so let us grab a subset of
              // the buffer and draw our lines
              this.DrawSection(g, start, i - start);
              start = i;
            }

            previous = current;
          }

          if (start < _snakeBody.Size)
          {
            this.DrawSection(g, start, _snakeBody.Size - start);
          }
        }
      }

      g.DrawEllipse(_headPen, new Rectangle(_snakeHead.X - _headSize, _snakeHead.Y - _headSize, _gridSize, _gridSize));
    }

    protected override void OnShown(EventArgs e)
    {
      Size size;

      size = this.ClientSize;
      _turnChance = 0.2;
      _snakeBody = new CircularBuffer<Point>(256);
      _snakeHead = new Point(size.Width / 2, size.Height / 2);
      _direction = Direction.Right;
      _buffer = new Point[0];
      _gridSize = 12;
      _headSize = _gridSize / 2;
      _bodyPen = new Pen(Color.CornflowerBlue)
      {
        Width = _gridSize / 2,
        EndCap = LineCap.Round,
        StartCap = LineCap.Round,
        LineJoin = LineJoin.Round
      };
      _headPen = new Pen(Color.SlateBlue)
      {
        Width = _gridSize / 2,
        EndCap = LineCap.Round,
        StartCap = LineCap.Round,
        LineJoin = LineJoin.Round
      };
      _random = new Random(20200805);

      this.SetupInitial();

      base.OnShown(e);
    }

    #endregion Protected Methods

    #region Private Methods

    private void AutomaticCheckBox_CheckedChanged(object sender, EventArgs e)
    {
      snakeTimer.Enabled = automaticCheckBox.Checked;
    }

    private void DrawSection(Graphics g, int start, int length)
    {
      if (length > 1) // DrawLines crashes if there isn't at least two points
      {
        this.EnsureSize(ref _buffer, length);
        _snakeBody.CopyTo(start, _buffer, 0, length);
        g.DrawLines(_bodyPen, _buffer);
      }
    }

    private void EnsureSize(ref Point[] buffer, int size)
    {
      if (buffer.Length != size)
      {
        buffer = new Point[size];
      }
    }

    private int GetDistance(Point p1, Point p2)
    {
      return this.GetDistance(p1.X, p1.Y, p2.X, p2.Y);
    }

    private int GetDistance(int x1, int y1, int x2, int y2)
    {
      float dx;
      float dy;

      dx = x1 - x2;
      dy = y1 - y2;

      return (int)Math.Sqrt((dx * dx) + (dy * dy));
    }

    private Size GetHeading()
    {
      int x;
      int y;

      if (_direction == Direction.Up)
      {
        x = 0;
        y = -_gridSize;
      }
      else if (_direction == Direction.Down)
      {
        x = 0;
        y = _gridSize;
      }
      else if (_direction == Direction.Left)
      {
        x = -_gridSize;
        y = 0;
      }
      else if (_direction == Direction.Right)
      {
        x = _gridSize;
        y = 0;
      }
      else
      {
        x = 0;
        y = 0;
      }

      return new Size(x, y);
    }

    private Direction GetRandomDirection()
    {
      Direction newDirection;
      double sample;

      sample = _random.NextDouble();

      if (sample < _turnChance)
      {
        newDirection = _direction - 1;
        if (newDirection < Direction.Up)
        {
          newDirection = Direction.Left;
        }
      }
      else if (sample > 1D - _turnChance)
      {
        newDirection = _direction + 1;
        if (newDirection > Direction.Left)
        {
          newDirection = Direction.Up;
        }
      }
      else
      {
        newDirection = _direction;
      }

      return newDirection;
    }

    private bool HasSplitResults()
    {
      bool result;

      result = false;

      for (int i = 1; i < _snakeBody.Size; i++)
      {
        if (this.GetDistance(_snakeBody.PeekAt(i - 1), _snakeBody.PeekAt(i)) > _gridSize)
        {
          result = true;
          break;
        }
      }

      return result;
    }

    private void NextButton_Click(object sender, EventArgs e)
    {
      this.NextMove();
    }

    private void NextMove()
    {
      int x;
      int y;
      Size heading;
      Size field;

      _moveCount++;

      _snakeBody.Put(_snakeHead);

      heading = this.GetHeading();
      field = this.ClientSize;
      x = _snakeHead.X + heading.Width;
      y = _snakeHead.Y + heading.Height;

      if (wrapCheckBox.Checked)
      {
        if (x < 0)
        {
          x = field.Width - 1;
        }
        else if (x >= field.Width)
        {
          x = 0;
        }

        if (y < 0)
        {
          y = field.Height - 1;
        }
        else if (y >= field.Height)
        {
          y = 0;
        }

        _snakeHead = new Point(x, y);
      }
      else if (x >= 0 && y >= 0 && x < field.Width && y < field.Height)
      {
        _snakeHead = new Point(x, y);
      }

      _direction = this.GetRandomDirection();

      this.Invalidate();
    }

    private void SetupInitial()
    {
      string[] args;

      args = Environment.GetCommandLineArgs();

      if (args.Length == 2 && long.TryParse(args[1], out long count))
      {
        automaticCheckBox.Checked = false;

        for (int i = 0; i < count; i++)
        {
          this.NextMove();
        }
      }
      else
      {
        snakeTimer.Enabled = true;
      }
    }

    private void SnakeTimer_Tick(object sender, EventArgs e)
    {
      this.NextMove();
    }

    #endregion Private Methods
  }
}


<|start_filename|>tests/Properties/AssemblyInfo.cs<|end_filename|>
using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("Cyotek.Collections.Generic.CircularBuffer (Tests)")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Cyotek.Collections.Generic.CircularBuffer")]
[assembly: AssemblyCopyright("Copyright © 2014-2020 Cyotek Ltd. All Rights Reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: Guid("c82afd42-a3ab-490a-8719-242299d75b01")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]


<|start_filename|>tests/CircularBufferTests.cs<|end_filename|>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;

namespace Cyotek.Collections.Generic.CircularBuffer.Tests
{
  [TestFixture]
  public class CircularBufferTests
  {
    #region  Tests

    [Test]
    public void CapacityExceptionTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;

      expected = 3;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");

      // act
      Assert.That(() => target.Capacity = expected, Throws.TypeOf<ArgumentOutOfRangeException>());
    }

    [Test]
    public void CapacityExistingItemsTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedCapacity;
      string[] expectedItems;
      int expectedSize;

      expectedCapacity = 10;
      expectedSize = 2;
      expectedItems = new[]
                      {
                        "Alpha",
                        "Beta"
                      };

      target = new CircularBuffer<string>(3);
      target.Put("Alpha");
      target.Put("Beta");

      // act
      target.Capacity = expectedCapacity;

      // assert
      Assert.AreEqual(expectedCapacity, target.Capacity);
      Assert.AreEqual(expectedSize, target.Size);
      CollectionAssert.AreEqual(expectedItems, target.ToArray());
    }

    [Test]
    public void CapacitySmallerTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;

      expected = 3;

      target = new CircularBuffer<string>(10);

      // act
      target.Capacity = expected;

      // assert
      Assert.AreEqual(expected, target.Capacity);
    }

    [Test]
    public void CapacityTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;

      expected = 10;

      target = new CircularBuffer<string>(3);

      // act
      target.Capacity = expected;

      // assert
      Assert.AreEqual(expected, target.Capacity);
    }

    [Test]
    public void ClearTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;

      expectedHead = 0;
      expectedSize = 0;
      expectedTail = 0;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.Clear();

      // assert
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void CollectionAddTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      string expected;

      target = new CircularBuffer<string>(10);

      expected = "Alpha";
      expectedHead = 0;
      expectedSize = 1;
      expectedTail = 1;

      // act
      ((ICollection<string>)target).Add(expected);

      // assert
      Assert.IsTrue(target.Contains(expected));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void CollectionCopyToTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedHead;
      string[] expected;
      string[] actual;
      int offset;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Zeta",
                   "Alpha",
                   "Beta",
                   "Gamma"
                 };
      actual = new[]
               {
                 "Zeta",
                 null,
                 null,
                 null
               };

      expectedHead = 0;
      offset = 1;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      ((ICollection)target).CopyTo(actual, offset);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsTrue(target.Contains("Alpha"));
      Assert.IsTrue(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
    }

    [Test]
    public void CollectionCountTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;
      int actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      expected = 3;

      // act
      actual = ((ICollection)target).Count;

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void CollectionIsReadOnlyTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);

      // act
      actual = ((ICollection<string>)target).IsReadOnly;

      // assert
      Assert.IsFalse(actual);
    }

    [Test]
    public void CollectionIsSynchronizedTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);

      // act
      actual = ((ICollection)target).IsSynchronized;

      // assert
      Assert.IsFalse(actual);
    }

    [Test]
    public void CollectionRemoveTest()
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");

      // act & assert
      Assert.That(() => ((ICollection<string>)target).Remove("Alpha"), Throws.TypeOf<NotSupportedException>());
    }

    [Test]
    public void ConstructorCapacityExceptionTest()
    {
      // act & assert
      Assert.That(() => new CircularBuffer<string>(-1), Throws.TypeOf<ArgumentException>());
    }

    [Test]
    public void ConstructorWithCapacityAndDefaultOverflowTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedCapacity;

      expectedCapacity = 10;

      // act
      target = new CircularBuffer<string>(expectedCapacity);

      // assert
      Assert.AreEqual(expectedCapacity, target.Capacity);
      Assert.IsTrue(target.AllowOverwrite);
    }

    [Test]
    public void ConstructorWithoutOverflowTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedCapacity;

      expectedCapacity = 10;

      // act
      target = new CircularBuffer<string>(expectedCapacity, false);

      // assert
      Assert.AreEqual(expectedCapacity, target.Capacity);
      Assert.IsFalse(target.AllowOverwrite);
    }

    [Test]
    public void ConstructorWithOverflowTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedCapacity;

      expectedCapacity = 10;

      // act
      target = new CircularBuffer<string>(expectedCapacity, true);

      // assert
      Assert.AreEqual(expectedCapacity, target.Capacity);
      Assert.IsTrue(target.AllowOverwrite);
    }

    [Test]
    public void ContainsAfterGetTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      target.Get();

      // act
      actual = target.Contains("Alpha");

      // assert
      Assert.IsFalse(actual);
    }

    [Test]
    public void ContainsNegativeTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.Contains("Delta");

      // assert
      Assert.IsFalse(actual);
    }

    [Test]
    public void ContainsTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.Contains("Alpha");

      // assert
      Assert.IsTrue(actual);
    }

    [Test]
    public void CopyToArrayWithOffsetAndCountTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedHead;
      string[] expected;
      string[] actual;
      int offset;
      int count;
      int index;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Zeta",
                   "Alpha",
                   "Beta",
                   "Eta"
                 };
      actual = new[]
               {
                 "Zeta",
                 null,
                 null,
                 "Eta"
               };

      expectedHead = 0;
      index = 0;
      offset = 1;
      count = 2;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.CopyTo(index, actual, offset, count);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsTrue(target.Contains("Alpha"));
      Assert.IsTrue(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
    }

    [Test]
    public void CopyToArrayWithOffsetTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedHead;
      string[] expected;
      string[] actual;
      int offset;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Zeta",
                   "Alpha",
                   "Beta",
                   "Gamma"
                 };
      actual = new[]
               {
                 "Zeta",
                 null,
                 null,
                 null
               };

      expectedHead = 0;
      offset = 1;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.CopyTo(actual, offset);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsTrue(target.Contains("Alpha"));
      Assert.IsTrue(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
    }

    [Test]
    public void CopyToArrayWithStartingIndexOffsetAndCountTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedHead;
      string[] expected;
      string[] actual;
      int offset;
      int count;
      int index;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Zeta",
                   "Beta",
                   "Gamma",
                   "Eta"
                 };
      actual = new[]
               {
                 "Zeta",
                 null,
                 null,
                 "Eta"
               };

      expectedHead = 0;
      index = 1;
      offset = 1;
      count = 2;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.CopyTo(index, actual, offset, count);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsTrue(target.Contains("Alpha"));
      Assert.IsTrue(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
    }

    [Test]
    public void CopyToExceptionTest()
    {
      // arrange
      CircularBuffer<string> target;
      string[] actual;
      int offset;
      int count;
      int index;

      target = new CircularBuffer<string>(10);
      actual = new string[target.Capacity];

      index = 0;
      offset = 0;
      count = 4;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act & assert
      Assert.That(() => target.CopyTo(index, actual, offset, count), Throws.TypeOf<ArgumentOutOfRangeException>());
    }

    [Test]
    public void CopyToTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedHead;
      string[] expected;
      string[] actual;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Alpha",
                   "Beta",
                   "Gamma"
                 };
      expectedHead = 0;

      actual = new string[3];

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.CopyTo(actual);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsTrue(target.Contains("Alpha"));
      Assert.IsTrue(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
    }

    [Test]
    public void EmptyBufferTest()
    {
      // arrange
      CircularBuffer<byte> target;
      byte[] expected;
      byte[] actual;

      expected = this.GenerateRandomData(100);

      target = new CircularBuffer<byte>(expected.Length);
      target.Put(expected);

      actual = new byte[target.Size];

      // act
      target.Get(actual);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.AreEqual(0, target.Size);
    }

    [Test]
    public void EnumeratorAfterGetTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      List<string> expected;
      List<string> actual;

      target = new CircularBuffer<string>(10);

      expected = new List<string>(new[]
                                  {
                                    "Beta",
                                    "Gamma"
                                  });
      expectedHead = 1;
      expectedSize = 2;
      expectedTail = 3;

      actual = new List<string>();

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Get();

      // act
      // ReSharper disable once LoopCanBeConvertedToQuery
      foreach (string value in target)
      {
        actual.Add(value);
      }

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void GenericCollectionCountTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;
      int actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      expected = 3;

      // act
      actual = ((ICollection<string>)target).Count;

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void GetEmptyExceptionTest()
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Get();
      target.Get();
      target.Get();

      // act & assert
      Assert.That(() => target.Get(), Throws.TypeOf<InvalidOperationException>());
    }

    [Test]
    public void GetEnumeratorTest()
    {
      // arrange
      CircularBuffer<string> target;
      List<string> expected;
      List<string> actual;
      IEnumerator<string> enumerator;

      target = new CircularBuffer<string>(3);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");

      expected = new List<string>(new[]
                                  {
                                    "Beta",
                                    "Gamma",
                                    "Delta"
                                  });
      actual = new List<string>();

      // act
      enumerator = target.GetEnumerator();
      while (enumerator.MoveNext())
      {
        actual.Add(enumerator.Current);
      }

      // assert
      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    public void GetLast_handles_wrapped_tail()
    {
      // arrange
      CircularBuffer<string> target;
      string expected;
      string actual;

      target = new CircularBuffer<string>(3);

      expected = "Gamma";

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.GetLast();

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void GetLast_should_decrease_size()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;
      int actual;

      target = new CircularBuffer<string>(10);

      expected = 2;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.GetLast();

      // assert
      actual = target.Size;
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void GetLast_should_decrease_tail()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;
      int actual;

      target = new CircularBuffer<string>(10);

      expected = 2;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.GetLast();

      // assert
      actual = target.Tail;
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void GetLast_should_not_affect_existing_items()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual1;
      bool actual2;

      target = new CircularBuffer<string>(10);

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.GetLast();

      // assert
      actual1 = target.Contains("Alpha");
      actual2 = target.Contains("Beta");
      Assert.IsTrue(actual1);
      Assert.IsTrue(actual2);
    }

    [Test]
    public void GetLast_should_remove_item()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      target.GetLast();

      // assert
      actual = target.Contains("Gamma");
      Assert.IsFalse(actual);
    }

    [Test]
    public void GetLast_should_return_last_added_item()
    {
      // arrange
      CircularBuffer<string> target;
      string expected;
      string actual;

      target = new CircularBuffer<string>(10);

      expected = "Gamma";

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.GetLast();

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void GetLast_throws_exception_if_buffer_empty()
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Get();
      target.Get();
      target.Get();

      // act & assert
      Assert.That(() => target.GetLast(), Throws.TypeOf<InvalidOperationException>());
    }

    [Test]
    public void GetNextTest()
    {
      // arrange
      CircularBuffer<string> target;
      string expected;
      string actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Get();

      expected = "Beta";

      // act
      actual = target.Get();

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void GetResetHeadAtCapacityTest()
    {
      // arrange
      CircularBuffer<string> target;
      string expected;
      string actual;
      int expectedHead;

      target = new CircularBuffer<string>(3);

      expected = "Gamma";
      expectedHead = 0;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      target.Get();
      target.Get();

      // act
      actual = target.Get();

      // assert
      Assert.AreEqual(expected, actual);
      Assert.AreEqual(expectedHead, target.Head);
    }

    [Test]
    public void GetTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      string expected;
      string actual;

      target = new CircularBuffer<string>(10);

      expected = "Alpha";
      expectedHead = 1;
      expectedSize = 2;
      expectedTail = 3;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.Get();

      // assert
      Assert.AreEqual(expected, actual);
      Assert.IsFalse(target.Contains("Alpha"));
      Assert.IsTrue(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void GetWithArrayAndOffsetTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      int expectedElements;
      int actualElements;
      string[] expected;
      string[] actual;
      int offset;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   null,
                   "Alpha",
                   "Beta"
                 };
      expectedHead = 2;
      expectedSize = 2;
      expectedTail = 4;
      expectedElements = 2;

      offset = 1;

      actual = new string[3];

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");

      // act
      actualElements = target.Get(actual, offset, expectedElements);

      // assert
      Assert.AreEqual(expectedElements, actualElements);
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsFalse(target.Contains("Alpha"));
      Assert.IsFalse(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.IsTrue(target.Contains("Delta"));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void GetWithArrayTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      int expectedElements;
      int actualElements;
      string[] expected;
      string[] actual;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Alpha",
                   "Beta"
                 };
      expectedHead = 2;
      expectedSize = 1;
      expectedTail = 3;
      expectedElements = 2;

      actual = new string[expectedElements];

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actualElements = target.Get(actual);

      // assert
      Assert.AreEqual(expectedElements, actualElements);
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsFalse(target.Contains("Alpha"));
      Assert.IsFalse(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void GetWithArrayWrapBufferTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedElements;
      int actualElements;
      string[] expected;
      string[] actual;

      target = new CircularBuffer<string>(4);

      expected = new[]
                 {
                   "Beta",
                   "Gamma",
                   "Delta",
                   "Epsilon"
                 };
      expectedElements = 4;

      actual = new string[expectedElements];

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");
      target.Put("Epsilon");

      // act
      actualElements = target.Get(actual);

      // assert
      Assert.AreEqual(expectedElements, actualElements);
      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    public void GetWithCountTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      string[] expected;
      string[] actual;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Alpha",
                   "Beta"
                 };
      expectedHead = 2;
      expectedSize = 1;
      expectedTail = 3;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.Get(2);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsFalse(target.Contains("Alpha"));
      Assert.IsFalse(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void GetLastWithCountTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      string[] expected;
      string[] actual;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Beta",
                   "Gamma"
                 };
      expectedHead = 0;
      expectedSize = 1;
      expectedTail = 1;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.GetLast(2);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsTrue(target.Contains("Alpha"));
      Assert.IsFalse(target.Contains("Beta"));
      Assert.IsFalse(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);

    }

    [Test]
    public void PeekLastWithCountTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      string[] expected;
      string[] actual;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Beta",
                   "Gamma"
                 };
      expectedHead = 0;
      expectedSize = 3;
      expectedTail = 3;

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.PeekLast(2);

      // assert
      CollectionAssert.AreEqual(expected, actual);
      Assert.IsTrue(target.Contains("Alpha"));
      Assert.IsTrue(target.Contains("Beta"));
      Assert.IsTrue(target.Contains("Gamma"));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void GetWithTooLargeCountTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedElements;
      int actualElements;
      string[] expected;
      string[] actual;
      int offset;
      int count;

      target = new CircularBuffer<string>(10);

      expected = new[]
                 {
                   "Alpha",
                   "Beta",
                   "Gamma",
                   "Delta",
                   null,
                   null,
                   null,
                   null
                 };
      expectedElements = 4;

      offset = 0;
      count = 8;

      actual = new string[count];

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");

      // act
      actualElements = target.Get(actual, offset, count);

      // assert
      Assert.AreEqual(expectedElements, actualElements);
      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    public void GetWrapBufferTest()
    {
      // arrange
      CircularBuffer<string> target;
      string expected;
      string actual;

      target = new CircularBuffer<string>(3);

      expected = "Delta";

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");
      target.Put("Epsilon");
      target.Put("Zeta");

      // act
      actual = target.Get();

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void IsEmptyNegativeTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);

      // act
      actual = target.IsEmpty;

      // assert
      Assert.IsTrue(actual);
    }

    [Test]
    public void IsEmptyTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);

      target.Put("Alpha");

      // act
      actual = target.IsEmpty;

      // assert
      Assert.IsFalse(actual);
    }

    [Test]
    public void IsFullNegativeTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(10);

      target.Put("Alpha");

      // act
      actual = target.IsFull;

      // assert
      Assert.IsFalse(actual);
    }

    [Test]
    public void IsFullTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(3, false);

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.IsFull;

      // assert
      Assert.IsTrue(actual);
    }

    [Test]
    public void IsFullWrapTest()
    {
      // arrange
      CircularBuffer<string> target;
      bool actual;

      target = new CircularBuffer<string>(3, true);

      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.IsFull;

      // assert
      Assert.IsFalse(actual);
    }

    [Test]
    public void PeekArrayEmptyExceptionTest()
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(10);

      // act & assert
      Assert.That(() => target.Peek(2), Throws.TypeOf<InvalidOperationException>());
    }

    [Test]
    public void PeekArrayTest()
    {
      // arrange
      CircularBuffer<string> target;
      string[] expected;
      string[] actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      expected = new[]
                 {
                   "Alpha",
                   "Beta"
                 };

      // act
      actual = target.Peek(2);

      // assert
      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    [TestCase(0, "Alpha")]
    [TestCase(1, "Beta")]
    [TestCase(2, "Gamma")]
    public void PeekAtTestCases(int index, string expected)
    {
      // arrange
      CircularBuffer<string> target;
      string actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      actual = target.PeekAt(index);

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void PeekAtWrapTest()
    {
      // arrange
      CircularBuffer<string> target;
      string actual;
      string expected;

      target = new CircularBuffer<string>(2);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      expected = "Gamma";

      // act
      actual = target.PeekAt(1);

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    [TestCase(-1)]
    [TestCase(3)]
    public void PeekAtEmptyExceptionTestCases(int index)
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      // act
      Assert.Throws<ArgumentOutOfRangeException>(() => target.PeekAt(index));
    }

    [Test]
    public void PeekAtAboveBoundsExceptionTest()
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(10);

      // act
      Assert.Throws<InvalidOperationException>(() => target.PeekAt(-1));
    }

    [Test]
    public void PeekEmptyExceptionTest()
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(10);

      // act & assert
      Assert.That(() => target.Peek(), Throws.TypeOf<InvalidOperationException>());
    }

    [Test]
    public void PeekLastEmptyExceptionTest()
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(10);

      // act & assert
      Assert.That(() => target.PeekLast(), Throws.TypeOf<InvalidOperationException>());
    }

    [Test]
    public void PeekLastTest()
    {
      // arrange
      CircularBuffer<string> target;
      string expected;
      string actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      expected = "Gamma";

      // act
      actual = target.PeekLast();

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void PeekLastWrapBufferTest()
    {
      // arrange
      CircularBuffer<string> target;
      string expected;
      string actual;

      target = new CircularBuffer<string>(3);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      expected = "Gamma";

      // act
      actual = target.PeekLast();

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void PeekTest()
    {
      // arrange
      CircularBuffer<string> target;
      string expected;
      string actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      expected = "Alpha";

      // act
      actual = target.Peek();

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void PutArrayExceptionTest()
    {
      // arrange
      CircularBuffer<byte> target;
      byte[] expected;

      expected = this.GenerateRandomData(100);

      target = new CircularBuffer<byte>(expected.Length, false);
      target.Put(byte.MaxValue);

      // act & assert
      Assert.That(() => target.Put(expected), Throws.TypeOf<InvalidOperationException>());
    }

    [Test]
    public void PutArrayTest()
    {
      // arrange
      CircularBuffer<byte> target;
      byte[] expected;

      expected = this.GenerateRandomData(100);

      target = new CircularBuffer<byte>(expected.Length);

      // act
      target.Put(expected);

      // assert
      CollectionAssert.AreEqual(expected, target.ToArray());
    }

    [Test]
    public void PutBufferFullExceptionTest()
    {
      // arrange
      CircularBuffer<string> target;

      target = new CircularBuffer<string>(2, false);

      target.Put("Alpha");
      target.Put("Beta");

      // act & assert
      Assert.That(() => target.Put("Gamma"), Throws.TypeOf<InvalidOperationException>());
    }

    [Test]
    public void PutMultipleTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      string expected1;
      string expected2;
      string expected3;

      target = new CircularBuffer<string>(10);

      expected1 = "Alpha";
      expected2 = "Beta";
      expected3 = "Gamma";
      expectedHead = 0;
      expectedSize = 3;
      expectedTail = 3;

      // act
      target.Put(expected1);
      target.Put(expected2);
      target.Put(expected3);

      // assert
      Assert.IsTrue(target.Contains(expected1));
      Assert.IsTrue(target.Contains(expected2));
      Assert.IsTrue(target.Contains(expected3));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void PutTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      string expected;

      target = new CircularBuffer<string>(10);

      expected = "Alpha";
      expectedHead = 0;
      expectedSize = 1;
      expectedTail = 1;

      // act
      target.Put(expected);

      // assert
      Assert.IsTrue(target.Contains(expected));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void PutWholeLengtWithCountToAllowOverwriteTest()
    {
      CircularBuffer<int> target;
      int[] actual;
      int[] expected;
      int bufSize = 3;
      target = new CircularBuffer<int>(bufSize, true);

      int[] values = new int[]
                     {
                       4,
                       5,
                       6,
                       7,
                       8
                     };
      expected = values.Take(bufSize).ToArray();
      target.Put(values, 0, bufSize);

      actual = target.ToArray();

      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    public void PutWholeLengtWithoutCountToAllowOverwriteTest()
    {
      CircularBuffer<int> target;
      int[] actual;
      int[] expected;
      int bufSize = 3;
      target = new CircularBuffer<int>(bufSize, true);

      int[] values = new int[]
                     {
                       4,
                       5,
                       6
                     };
      expected = values.Take(bufSize).ToArray();
      target.Put(values);

      actual = target.ToArray();

      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    public void PutWrapBufferTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expectedSize;
      int expectedHead;
      int expectedTail;
      string expected1;
      string expected2;
      string expected3;
      string expected4;

      target = new CircularBuffer<string>(3);

      expected1 = "Alpha";
      expected2 = "Beta";
      expected3 = "Gamma";
      expected4 = "Delta";
      expectedHead = 1;
      expectedSize = 3;
      expectedTail = 1;

      // act
      target.Put(expected1);
      target.Put(expected2);
      target.Put(expected3);
      target.Put(expected4);

      // assert
      Assert.IsFalse(target.Contains(expected1));
      Assert.IsTrue(target.Contains(expected2));
      Assert.IsTrue(target.Contains(expected3));
      Assert.IsTrue(target.Contains(expected4));
      Assert.AreEqual(expectedHead, target.Head);
      Assert.AreEqual(expectedTail, target.Tail);
      Assert.AreEqual(expectedSize, target.Size);
    }

    [Test]
    public void SizeTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;
      int actual;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");

      expected = 3;

      // act
      actual = target.Size;

      // assert
      Assert.AreEqual(expected, actual);
    }

    [Test]
    public void SkipOverCapacityTest()
    {
      // arrange
      CircularBuffer<byte> target;
      int expectedHead;

      target = new CircularBuffer<byte>(100, true);
      target.Skip(75);
      expectedHead = 25;

      // act
      target.Skip(50);

      // assert
      Assert.AreEqual(expectedHead, target.Head);
    }

    [Test]
    public void SkipTest()
    {
      // arrange
      CircularBuffer<string> target;
      int expected;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");

      expected = 2;

      // act
      target.Skip(2);

      // assert
      Assert.AreEqual(expected, target.Head);
    }

    [Test]
    public void SkipWrapBufferTest()
    {
      // arrange
      CircularBuffer<byte> target;
      byte[] dataIn;

      dataIn = this.GenerateRandomData(100);
      int HL = dataIn.Length / 2;
      target = new CircularBuffer<byte>(dataIn.Length, true);
      target.Put(this.GenerateRandomData(HL));
      target.Put(dataIn);

      byte[] expected = new byte[dataIn.Length];
      Buffer.BlockCopy(dataIn, 0, expected, HL, HL);
      Buffer.BlockCopy(dataIn, HL, expected, 0, HL);

      // act
      target.Skip(HL);

      byte[] actual = target.ToArray();
      // assert
      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    public void ToArrayTest()
    {
      // arrange
      CircularBuffer<string> target;
      string[] actual;
      string[] expected;

      target = new CircularBuffer<string>(10);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");

      expected = new[]
                 {
                   "Alpha",
                   "Beta",
                   "Gamma",
                   "Delta"
                 };

      // act
      actual = target.ToArray();

      // assert
      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    public void ToArrayWrapBufferTest()
    {
      // arrange
      CircularBuffer<string> target;
      string[] actual;
      string[] expected;

      target = new CircularBuffer<string>(3);
      target.Put("Alpha");
      target.Put("Beta");
      target.Put("Gamma");
      target.Put("Delta");

      expected = new[]
                 {
                   "Beta",
                   "Gamma",
                   "Delta"
                 };

      // act
      actual = target.ToArray();

      // assert
      CollectionAssert.AreEqual(expected, actual);
    }

    #endregion

    #region Test Helpers

    private Random _random;

    [OneTimeTearDown]
    public void CleanUp()
    {
      _random = null;
    }

    [OneTimeSetUp]
    public void Setup()
    {
      _random = new Random();
    }

    protected byte[] GenerateRandomData(int length)
    {
      byte[] result;

      result = new byte[length];
      _random.NextBytes(result);

      return result;
    }

    #endregion

    [Test]
    public void CopyToRangeWrappedTest()
    {
      // arrange
      CircularBuffer<int> target;
      int[] expected;
      int[] actual;

      target = new CircularBuffer<int>(10);
      for (int i = 0; i < 16; i++)
      {
        target.Put(i);
      }

      expected = new[]
      {
        6,
        7,
        8,
        9,
        10,
        11,
        12,
        13,
        14,
        15
      };

      actual = new int[10];

      // act
      target.CopyTo(0, actual, 0, target.Size);

      // assert
      CollectionAssert.AreEqual(expected, actual);
    }

    [Test]
    public void CopyToRangeOffsetTest()
    {
      // arrange
      CircularBuffer<int> target;
      int[] expected;
      int[] actual;

      target = new CircularBuffer<int>(10);
      for (int i = 0; i < 16; i++)
      {
        target.Put(i);
      }

      expected = new[]
      {
        12,
        13,
        14,
        15,
        6,
        7,
        8,
        9,
        10,
        11,
      };

      actual = new int[10];

      // act
      target.CopyTo(6, actual, 0, target.Size);

      // assert
      CollectionAssert.AreEqual(expected, actual);
    }
  }
}


<|start_filename|>runtests.cmd<|end_filename|>
@ECHO OFF

SETLOCAL

SET SCRIPTPATH=%~dp0
SET SCRIPTPATH=%SCRIPTPATH:~0,-1%

CD %SCRIPTPATH%

CALL ..\..\..\build\set35vars.bat

SET RESULTDIR=%1
IF "%RESULTDIR%"=="" SET RESULTDIR=testresults

IF NOT EXIST %RESULTDIR% MKDIR %RESULTDIR%

SET DLLNAME=Cyotek.Collections.Generic.CircularBuffer.Tests
SET SRCDIR=%DLLNAME%\
SET SLNNAME=Cyotek.Collections.Generic.CircularBuffer.sln

%NUGETEXE% restore %SLNNAME%

%MSBUILDEXE% %SLNNAME% %cbbuild%
IF %ERRORLEVEL% NEQ 0 GOTO :testsfailed

%nunitexe% %SRCDIR%bin\release\%DLLNAME%.dll -result=testresults\%DLLNAME%.xml %nunitargs%
IF %ERRORLEVEL% NEQ 0 GOTO :testsfailed

ENDLOCAL

GOTO :eof

:testsfailed
CECHO {0c}ERROR: *** TEST RUN FAILED ***{#}{\n}
EXIT /b 1


<|start_filename|>build.cmd<|end_filename|>
@ECHO OFF

SETLOCAL

CALL ..\..\..\build\set35vars.bat

SET BASENAME=Cyotek.Collections.Generic.CircularBuffer
SET RELDIR=src\bin\Release\
SET PRJFILE=src\%BASENAME%.csproj
SET DLLNAME=%BASENAME%.dll

IF EXIST %RELDIR%*.nupkg DEL /F %RELDIR%*.nupkg
IF EXIST %RELDIR%*.snupkg DEL /F %RELDIR%*.snupkg

dotnet build %PRJFILE% --configuration Release

CALL signcmd %RELDIR%net35\%DLLNAME%
CALL signcmd %RELDIR%net40\%DLLNAME%
CALL signcmd %RELDIR%net452\%DLLNAME%
CALL signcmd %RELDIR%net462\%DLLNAME%
CALL signcmd %RELDIR%net472\%DLLNAME%
CALL signcmd %RELDIR%net48\%DLLNAME%
CALL signcmd %RELDIR%netcoreapp2.1\%DLLNAME%
CALL signcmd %RELDIR%netcoreapp2.2\%DLLNAME%
CALL signcmd %RELDIR%netcoreapp3.1\%DLLNAME%
CALL signcmd %RELDIR%netstandard2.0\%DLLNAME%
CALL signcmd %RELDIR%netstandard2.1\%DLLNAME%

dotnet pack %PRJFILE% --configuration Release --no-build

CALL sign-package %RELDIR%*.nupkg
CALL sign-package %RELDIR%*.snupkg

ENDLOCAL


<|start_filename|>demo/DemoForm.Designer.cs<|end_filename|>
namespace Cyotek.Collections.Generic.CircularBuffer.Demo
{
  partial class DemoForm
  {
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
      }
      base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.components = new System.ComponentModel.Container();
      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DemoForm));
      this.snakeTimer = new System.Windows.Forms.Timer(this.components);
      this.wrapCheckBox = new System.Windows.Forms.CheckBox();
      this.label1 = new System.Windows.Forms.Label();
      this.nextButton = new System.Windows.Forms.Button();
      this.automaticCheckBox = new System.Windows.Forms.CheckBox();
      this.SuspendLayout();
      // 
      // snakeTimer
      // 
      this.snakeTimer.Interval = 25;
      this.snakeTimer.Tick += new System.EventHandler(this.SnakeTimer_Tick);
      // 
      // wrapCheckBox
      // 
      this.wrapCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
      this.wrapCheckBox.AutoSize = true;
      this.wrapCheckBox.BackColor = System.Drawing.Color.Transparent;
      this.wrapCheckBox.Checked = true;
      this.wrapCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
      this.wrapCheckBox.ForeColor = System.Drawing.Color.FromArgb(8, 8, 8);
      this.wrapCheckBox.Location = new System.Drawing.Point(720, 532);
      this.wrapCheckBox.Name = "wrapCheckBox";
      this.wrapCheckBox.Size = new System.Drawing.Size(52, 17);
      this.wrapCheckBox.TabIndex = 3;
      this.wrapCheckBox.Text = "&Wrap";
      this.wrapCheckBox.UseVisualStyleBackColor = false;
      // 
      // label1
      // 
      this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
      this.label1.BackColor = System.Drawing.Color.Transparent;
      this.label1.ForeColor = System.Drawing.Color.FromArgb(8, 8, 8);
      this.label1.Location = new System.Drawing.Point(12, 522);
      this.label1.Name = "label1";
      this.label1.Size = new System.Drawing.Size(674, 30);
      this.label1.TabIndex = 2;
      this.label1.Text = resources.GetString("label1.Text");
      // 
      // nextButton
      // 
      this.nextButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
      this.nextButton.Location = new System.Drawing.Point(697, 41);
      this.nextButton.Name = "nextButton";
      this.nextButton.Size = new System.Drawing.Size(75, 23);
      this.nextButton.TabIndex = 1;
      this.nextButton.Text = "&Next";
      this.nextButton.UseVisualStyleBackColor = true;
      this.nextButton.Click += new System.EventHandler(this.NextButton_Click);
      // 
      // automaticCheckBox
      // 
      this.automaticCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
      this.automaticCheckBox.Appearance = System.Windows.Forms.Appearance.Button;
      this.automaticCheckBox.Checked = true;
      this.automaticCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
      this.automaticCheckBox.Location = new System.Drawing.Point(697, 12);
      this.automaticCheckBox.Name = "automaticCheckBox";
      this.automaticCheckBox.Size = new System.Drawing.Size(75, 23);
      this.automaticCheckBox.TabIndex = 0;
      this.automaticCheckBox.Text = "&Automatic";
      this.automaticCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
      this.automaticCheckBox.UseVisualStyleBackColor = true;
      this.automaticCheckBox.CheckedChanged += new System.EventHandler(this.AutomaticCheckBox_CheckedChanged);
      // 
      // DemoForm
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
      this.ClientSize = new System.Drawing.Size(784, 561);
      this.Controls.Add(this.automaticCheckBox);
      this.Controls.Add(this.nextButton);
      this.Controls.Add(this.label1);
      this.Controls.Add(this.wrapCheckBox);
      this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
      this.Name = "DemoForm";
      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
      this.Text = "Cyotek CircularBuffer CopyTo Demonstration";
      this.ResumeLayout(false);
      this.PerformLayout();

    }

    #endregion

    private System.Windows.Forms.Timer snakeTimer;
    private System.Windows.Forms.CheckBox wrapCheckBox;
    private System.Windows.Forms.Label label1;
    private System.Windows.Forms.Button nextButton;
    private System.Windows.Forms.CheckBox automaticCheckBox;
  }
}



<|start_filename|>src/Properties/AssemblyInfo.cs<|end_filename|>
using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
[assembly: Guid("1a902c02-561d-48c4-9fe3-0c3c707589d7")]
[assembly: AssemblyVersion("1.0.0.0")]
