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

<TestClass()> _
Public Class ConcurrentDictionary_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 Can_initialize_dictionary_with_objects_and_lookup()
        Dim kvColl = New List(Of KeyValuePair(Of String, Integer))()
        kvColl.Add(New KeyValuePair(Of String, Integer)("zero", 0))
        kvColl.Add(New KeyValuePair(Of String, Integer)("one", 1))
        kvColl.Add(New KeyValuePair(Of String, Integer)("two", 2))
        kvColl.Add(New KeyValuePair(Of String, Integer)("three", 3))
        kvColl.Add(New KeyValuePair(Of String, Integer)("four", 4))
        kvColl.Add(New KeyValuePair(Of String, Integer)("five", 5))
        kvColl.Add(New KeyValuePair(Of String, Integer)("six", 6))
        kvColl.Add(New KeyValuePair(Of String, Integer)("seven", 7))
        kvColl.Add(New KeyValuePair(Of String, Integer)("eight", 8))
        kvColl.Add(New KeyValuePair(Of String, Integer)("nine", 9))
        Dim tsd = New ConcurrentDictionary(Of String, Integer)(kvColl, EqualityComparer(Of String).Default)
        Assert.IsNotNull(tsd)
        Assert.IsTrue(tsd.Count = 10)
        Assert.IsTrue(tsd.ContainsKey("six"))
        Assert.IsTrue(tsd.ContainsKey("nine"))
        Assert.AreEqual(tsd.Item("zero"), 0)
        Assert.AreEqual(tsd.Item("one"), 1)
        Assert.AreEqual(tsd.Item("two"), 2)
        Assert.AreEqual(tsd.Item("three"), 3)
        Assert.AreEqual(tsd.Item("four"), 4)
        Assert.AreEqual(tsd.Item("five"), 5)
        Assert.AreEqual(tsd.Item("six"), 6)
        Assert.AreEqual(tsd.Item("seven"), 7)
        Assert.AreEqual(tsd.Item("eight"), 8)
        Assert.AreEqual(tsd.Item("nine"), 9)
    End Sub

    <TestMethod()> _
    Public Sub Can_enumerate_dictionary_keyvalue_pairs()
        Dim kvColl = New List(Of KeyValuePair(Of Integer, String))()
        For i As Integer = 0 To 99999
            kvColl.Add(New KeyValuePair(Of Integer, String)(i, i.ToString()))
        Next
        Dim tsd = New ConcurrentDictionary(Of Integer, String)(kvColl, EqualityComparer(Of Integer).Default)
        Assert.IsNotNull(tsd)
        Dim test = New Dictionary(Of Integer, String)()
        For Each kv As KeyValuePair(Of Integer, String) In tsd
            test.Add(kv.Key, kv.Value)
        Next
        Assert.IsTrue(test.Count = tsd.Count)
    End Sub

    <TestMethod()> _
    Public Sub Can_enumerate_while_modifying()
        Dim kvColl = New List(Of KeyValuePair(Of Integer, String))()
        For i As Integer = 0 To 99999
            kvColl.Add(New KeyValuePair(Of Integer, String)(i, i.ToString()))
        Next
        Dim tsd = New ConcurrentDictionary(Of Integer, String)(kvColl, EqualityComparer(Of Integer).Default)
        Assert.IsNotNull(tsd)
        Dim ct = tsd.Count
        ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf _AddToDictionaryCallback), tsd)
        For i As Integer = 0 To ct - 1
            If i = 0 Then _
                Thread.Sleep(80)
        Next
        Thread.Sleep(1000)
        Assert.IsTrue(tsd.Count = ct + 1)
    End Sub

    Private Sub _AddToDictionaryCallback(ByVal state As Object)
        Dim dict = TryCast(state, ConcurrentDictionary(Of Integer, String))
        For i As Integer = 0 To 99999
            Assert.IsFalse(dict.TryAdd(i, i.ToString()))
        Next
        dict.TryAdd(100000, "100000")
    End Sub

End Class
