Imports System
Imports System.Text
Imports System.Collections.Generic
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports Mercury.Mobile

<TestClass()> _
Public Class CircularCache_specs

    Private testContextInstance As TestContext

    '''<summary>
    '''Gets or sets the test context which provides
    '''information about and functionality for the current test run.
    '''</summary>
    Public Property TestContext() As TestContext
        Get
            Return testContextInstance
        End Get
        Set(ByVal value As TestContext)
            testContextInstance = value
        End Set
    End Property

#Region "Additional test attributes"
    '
    ' You can use the following additional attributes as you write your tests:
    '
    ' Use ClassInitialize to run code before running the first test in the class
    ' <ClassInitialize()> Public Shared Sub MyClassInitialize(ByVal testContext As TestContext)
    ' End Sub
    '
    ' Use ClassCleanup to run code after all tests in a class have run
    ' <ClassCleanup()> Public Shared Sub MyClassCleanup()
    ' End Sub
    '
    ' Use TestInitialize to run code before running each test
    ' <TestInitialize()> Public Sub MyTestInitialize()
    ' End Sub
    '
    ' Use TestCleanup to run code after each test has run
    ' <TestCleanup()> Public Sub MyTestCleanup()
    ' End Sub
    '
#End Region

    <TestMethod()> _
    Public Sub Cache_overwrites_oldest_values_when_overfilled()
        Dim cache = New CircularCache(Of Integer, String)(55)
        Assert.IsNotNull(cache)
        Assert.IsTrue(cache.BufferSize = 55)
        Assert.IsTrue(cache.Count = 0)
        Assert.IsFalse(cache.IsReadOnly)

        ' Fill to max
        For i As Integer = 0 To 54
            cache.Add(i, String.Format("Item:{0}", i))
        Next
        Dim testValue As String = Nothing
        Dim flag As Boolean = cache.TryGetValue(0, testValue)
        Assert.IsNotNull(testValue)
        Assert.IsTrue(flag)
        Assert.IsTrue(testValue = "Item:0")
        Assert.IsTrue(cache.Count = 55)

        ' Attempt to add another value
        cache.Add(55, "Item:55")

        ' Test for overwrite
        testValue = Nothing
        flag = cache.TryGetValue(0, testValue)
        Assert.IsFalse(flag)
        Assert.IsNull(testValue)

        ' Test successful new value write
        flag = cache.TryGetValue(55, testValue)
        Assert.IsTrue(flag)
        Assert.IsNotNull(testValue)
        Assert.IsTrue(testValue = "Item:55")
        Assert.IsTrue(cache.Count = 55)

        ' Test item get
        testValue = cache.Item(23)
        Assert.IsNotNull(testValue)
        Assert.IsTrue(testValue = "Item:23")
    End Sub

    <TestMethod()> _
    Public Sub Can_remove_value_from_cache()
        Dim cache = New CircularCache(Of Integer, String)(55)
        Assert.IsNotNull(cache)
        Assert.IsTrue(cache.BufferSize = 55)
        Assert.IsTrue(cache.Count = 0)

        ' Fill to max
        Dim testValue As String = Nothing
        For i As Integer = 0 To 54
            cache.Add(i, String.Format("Item:{0}", i))
        Next
        Assert.IsTrue(cache.Count = 55)
        Assert.IsTrue(cache.TryGetValue(23, testValue))
        Assert.IsNotNull(testValue)
        Assert.IsTrue(testValue = "Item:23")

        ' Remove from middle
        Dim flag As Boolean = cache.Remove(23)
        Assert.IsTrue(flag)

        Assert.IsFalse(cache.TryGetValue(23, testValue))
        Assert.IsNull(testValue)
        Assert.IsTrue(cache.Count = 54)

        ' Add new value
        cache.Add(99, "Item:99")
        Assert.IsTrue(cache.Count = 55)

        ' Verify all values (excluding item 23)
        For i As Integer = 0 To 54
            testValue = Nothing
            If i <> 23 Then
                Assert.IsTrue(cache.TryGetValue(i, testValue))
                Assert.IsNotNull(testValue)
                Assert.IsTrue(testValue = String.Format("Item:{0}", i))
            End If
        Next
        ' Verify new value
        testValue = Nothing
        Assert.IsTrue(cache.TryGetValue(99, testValue))
        Assert.IsNotNull(testValue)
        Assert.IsTrue(testValue = "Item:99")
    End Sub

    <TestMethod()> _
    Public Sub Can_enumerate_cache_items()
        Dim cache = New CircularCache(Of Integer, String)(55)
        ' Fill to max
        Dim testValue As String = Nothing
        For i As Integer = 0 To 54
            cache.Add(i, String.Format("Item:{0}", i))
        Next
        
        ' Test implicit enumerator
        For Each kv As KeyValuePair(Of Integer, String) In cache
            Assert.IsTrue(kv.Value = String.Format("Item:{0}", kv.Key))
        Next
        Assert.IsTrue(cache.Count = 55)

        ' Remove values
        Assert.IsTrue(cache.Remove(23))
        Assert.IsTrue(cache.Remove(31))
        Assert.IsTrue(cache.Remove(44))
        Assert.IsTrue(cache.Count = 52)

        ' Test explicit enumerator
        Dim counter As Integer = 0
        Dim enumerator = cache.GetEnumerator()
        Dim current As KeyValuePair(Of Integer, String)
        Do While enumerator.MoveNext()
            current = enumerator.Current
            Assert.IsTrue(current.Value = String.Format("Item:{0}", current.Key))
            counter += 1
        Loop
        Assert.IsTrue(counter = cache.Count)
    End Sub

End Class
