namespace TweetTest.Data.TwoKeyDictionary open Xunit open TweetDuck.Data open System.Collections.Generic type _TestData = static member empty with get() = TwoKeyDictionary<string, int, float>() static member uniquevals with get() = let dict = TwoKeyDictionary<string, int, float>() dict.Add("first", 1, 10.0) dict.Add("first", 2, 20.0) dict.Add("first", 3, 30.0) dict.Add("second", 1, 100.0) dict.Add("second", 2, 200.0) dict.Add("third", 1, 1000.0) dict static member duplicatevals with get() = let dict = TwoKeyDictionary<string, int, float>() dict.Add("first", 1, 10.0) dict.Add("first", 2, 20.0) dict.Add("first", 3, 30.0) dict.Add("second", 1, 10.0) dict.Add("second", 2, 20.0) dict.Add("third", 1, 10.0) dict module Indexer = [<Theory>] [<InlineData("first", 3, 30.0)>] [<InlineData("second", 2, 200.0)>] [<InlineData("third", 1, 1000.0)>] let ``get returns correct value`` (outerKey: string, innerKey: int, value: float) = Assert.Equal(value, _TestData.uniquevals.[outerKey, innerKey]) [<Fact>] let ``get throws if outer key is missing`` () = Assert.Throws<KeyNotFoundException>(fun () -> _TestData.uniquevals.["missing", 1] |> ignore) [<Fact>] let ``get throws if inner key is missing`` () = Assert.Throws<KeyNotFoundException>(fun () -> _TestData.uniquevals.["first", 0] |> ignore) [<Fact>] let ``set correctly updates value`` () = let copy = _TestData.uniquevals copy.["first", 1] <- 50.0 Assert.Equal(50.0, copy.["first", 1]) [<Fact>] let ``set creates new inner key`` () = let copy = _TestData.uniquevals copy.["second", 3] <- 300.0 Assert.Equal(300.0, copy.["second", 3]) [<Fact>] let ``set creates new outer key`` () = let copy = _TestData.uniquevals copy.["fourth", 1] <- 10000.0 Assert.Equal(10000.0, copy.["fourth", 1]) module InnerValues = open System.Linq [<Fact>] let ``returns empty collection for empty dictionary`` () = Assert.Equal<IEnumerable<float>>(Enumerable.Empty<float>(), _TestData.empty.InnerValues) [<Fact>] let ``returns all values for dictionary with unique values`` () = Assert.Equal([ 10.0; 20.0; 30.0; 100.0; 200.0; 1000.0 ], _TestData.uniquevals.InnerValues) [<Fact>] let ``returns all values for dictionary with duplicated values`` () = Assert.Equal([ 10.0; 20.0; 30.0; 10.0; 20.0; 10.0 ], _TestData.duplicatevals.InnerValues) module TryGetValue = [<Fact>] let ``returns true and correct value for existing key`` () = let (success, result) = _TestData.uniquevals.TryGetValue("first", 3) Assert.True(success) Assert.Equal(30.0, result) [<Fact>] let ``returns false for missing inner key`` () = Assert.False(_TestData.uniquevals.TryGetValue("first", 0, ref 0.0)) [<Fact>] let ``returns false for missing outer key`` () = Assert.False(_TestData.uniquevals.TryGetValue("missing", 0, ref 0.0)) module Add = open System [<Fact>] let ``creates new inner key`` () = let copy = _TestData.uniquevals copy.Add("first", 4, 40.0) Assert.Equal(40.0, copy.["first", 4]) [<Fact>] let ``creates new outer key`` () = let copy = _TestData.uniquevals copy.Add("fourth", 1, 10000.0) Assert.Equal(10000.0, copy.["fourth", 1]) [<Fact>] let ``throw on duplicate key`` () = Assert.Throws<ArgumentException>(fun () -> _TestData.uniquevals.Add("first", 2, 25.0)) module Contains = [<Theory>] [<InlineData("first")>] [<InlineData("second")>] [<InlineData("third")>] let ``returns true if outer key exists`` (outerKey: string) = Assert.True(_TestData.uniquevals.Contains(outerKey)) [<Theory>] [<InlineData(1)>] [<InlineData(2)>] [<InlineData(3)>] let ``returns true if inner key exists`` (innerKey: int) = Assert.True(_TestData.uniquevals.Contains("first", innerKey)) [<Fact>] let ``returns false if outer key does not exist`` () = Assert.False(_TestData.uniquevals.Contains("missing")) [<Fact>] let ``returns false if inner key does not exist`` () = Assert.False(_TestData.uniquevals.Contains("first", 0)) module Count = [<Fact>] let ``counts all values for dictionary with unique values`` () = Assert.Equal(6, _TestData.uniquevals.Count()) [<Fact>] let ``counts all values for dictionary with duplicated values`` () = Assert.Equal(6, _TestData.duplicatevals.Count()) [<Theory>] [<InlineData("first", 3)>] [<InlineData("second", 2)>] [<InlineData("third", 1)>] let ``counts all values for specified key`` (outerKey: string, expectedCount: int) = Assert.Equal(expectedCount, _TestData.uniquevals.Count(outerKey)) [<Fact>] let ``throws on missing key`` () = Assert.Throws<KeyNotFoundException>(fun () -> _TestData.uniquevals.Count("missing") |> ignore) module Clear = [<Fact>] let ``clears all values for all keys`` () = let copy = _TestData.uniquevals copy.Clear() Assert.Equal(0, copy.Count()) [<Fact>] let ``clears all values for specified key`` () = let copy = _TestData.uniquevals copy.Clear("first") Assert.True(copy.Contains("first")) Assert.Equal(0, copy.Count("first")) Assert.Equal(3, copy.Count()) [<Fact>] let ``throws on missing key`` () = Assert.Throws<KeyNotFoundException>(fun () -> _TestData.uniquevals.Clear("missing") |> ignore) module Remove = [<Fact>] let ``removes value by key pair`` () = let copy = _TestData.uniquevals Assert.True(copy.Remove("first", 3)) Assert.False(copy.Contains("first", 3)) Assert.Equal(5, copy.Count()) [<Fact>] let ``removes inner key and its values`` () = let copy = _TestData.uniquevals Assert.True(copy.Remove("first")) Assert.False(copy.Contains("first")) Assert.Equal(3, copy.Count()) [<Fact>] let ``removing all inner keys deletes the outer key`` () = let copy = _TestData.uniquevals Assert.True(copy.Remove("first", 1)) Assert.True(copy.Remove("first", 2)) Assert.True(copy.Remove("first", 3)) Assert.False(copy.Contains("first")) [<Fact>] let ``returns false on missing inner key`` () = Assert.False(_TestData.uniquevals.Remove("first", 0)) [<Fact>] let ``returns false on missing outer key`` () = Assert.False(_TestData.uniquevals.Remove("missing"))