diff --git a/FruityFoundation.Tests.FsBase/ExtensionsTests.fs b/FruityFoundation.Tests.FsBase/ExtensionsTests.fs new file mode 100644 index 0000000..3bf6262 --- /dev/null +++ b/FruityFoundation.Tests.FsBase/ExtensionsTests.fs @@ -0,0 +1,70 @@ +module FruityFoundation.Tests.FsBase + +open System.Collections.Generic +open FruityFoundation.Base.Structures +open NUnit.Framework +open FsUnit +open FruityFoundation.FsBase + +[] +let ``Array.toReadOnlyCollection casts an array to a read only collection`` () = + // Arrange + let input = [|1; 2; 3|] + + // Act + let result = input |> Array.toReadOnlyCollection + + // Assert + result |> should be instanceOfType> + +[] +let ``Option.toMaybe returns an empty Maybe for None`` () = + // Arrange + let input : string option = None + + // Act + let result = input |> Option.toMaybe + + // Assert + Assert.That(result, Is.InstanceOf()) + result |> should be instanceOfType + result.HasValue |> should equal false + +[] +let ``Option.toMaybe returns Maybe for Some`` () = + // Arrange + let input : string option = Some "banana" + + // Act + let result = input |> Option.toMaybe + + // Assert + result |> should be instanceOfType + result.HasValue |> should equal true + result.Value |> should equal "banana" + +[] +let ``ValueOption.toMaybe returns an empty Maybe for None`` () = + // Arrange + let input : string ValueOption = ValueNone + + // Act + let result = input |> ValueOption.toMaybe + + // Assert + Assert.That(result, Is.InstanceOf()) + result |> should be instanceOfType + result.HasValue |> should equal false + +[] +let ``ValueOption.toMaybe returns Maybe for Some`` () = + // Arrange + let input : string ValueOption = ValueSome "banana" + + // Act + let result = input |> ValueOption.toMaybe + + // Assert + result |> should be instanceOfType + result.HasValue |> should equal true + result.Value |> should equal "banana" diff --git a/FruityFoundation.Tests.FsBase/FruityFoundation.Tests.FsBase.fsproj b/FruityFoundation.Tests.FsBase/FruityFoundation.Tests.FsBase.fsproj new file mode 100644 index 0000000..9bc12c0 --- /dev/null +++ b/FruityFoundation.Tests.FsBase/FruityFoundation.Tests.FsBase.fsproj @@ -0,0 +1,35 @@ + + + + + false + false + true + net8.0;net6.0 + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/FruityFoundation.Tests.FsBase/Program.fs b/FruityFoundation.Tests.FsBase/Program.fs new file mode 100644 index 0000000..176a7b6 --- /dev/null +++ b/FruityFoundation.Tests.FsBase/Program.fs @@ -0,0 +1,4 @@ +module Program = + + [] + let main _ = 0 diff --git a/FruityFoundation.Tests.FsBaseInterop/ExtensionTests.cs b/FruityFoundation.Tests.FsBaseInterop/ExtensionTests.cs new file mode 100644 index 0000000..b70b4d5 --- /dev/null +++ b/FruityFoundation.Tests.FsBaseInterop/ExtensionTests.cs @@ -0,0 +1,118 @@ +using FruityFoundation.Base.Structures; +using FruityFoundation.FsBase; +using Microsoft.FSharp.Core; + +namespace FruityFoundation.Tests.FsBaseInterop; + +public class ExtensionTests +{ + [Test] + public void Option_OfNone_ToMaybe_ReturnsEmptyMaybe() + { + // Arrange + var option = FSharpOption.None; + + // Act + var result = option.ToMaybe(); + + // Assert + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.HasValue, Is.False); + } + + [Test] + public void Option_OfSome_ToMaybe_ReturnsMaybe() + { + // Arrange + var option = FSharpOption.Some(25); + + // Act + var result = option.ToMaybe(); + + // Assert + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.HasValue, Is.True); + Assert.That(result.Value, Is.EqualTo(25)); + } + + [Test] + public void ValueOption_OfNone_ToMaybe_ReturnsEmptyMaybe() + { + // Arrange + var option = FSharpValueOption.None; + + // Act + var result = option.ToMaybe(); + + // Assert + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.HasValue, Is.False); + } + + [Test] + public void ValueOption_OfSome_ToMaybe_ReturnsMaybe() + { + // Arrange + var option = FSharpValueOption.Some(25); + + // Act + var result = option.ToMaybe(); + + // Assert + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.HasValue, Is.True); + Assert.That(result.Value, Is.EqualTo(25)); + } + + [Test] + public void EmptyMaybe_ToOption_ReturnsNone() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = maybe.ToOption(); + + // Assert + Assert.That(result, Is.EqualTo(FSharpOption.None)); + } + + [Test] + public void Maybe_ToOption_ReturnsSome() + { + // Arrange + var maybe = Maybe.Create(25); + + // Act + var result = maybe.ToOption(); + + // Assert + Assert.That(result, Is.EqualTo(FSharpOption.Some(25))); + } + + [Test] + public void EmptyMaybe_ToValueOption_ReturnsNone() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = maybe.ToValueOption(); + + // Assert + Assert.That(result, Is.EqualTo(FSharpValueOption.None)); + } + + [Test] + public void Maybe_ToValueOption_ReturnsSome() + { + // Arrange + var maybe = Maybe.Create(25); + + // Act + var result = maybe.ToValueOption(); + + // Assert + Assert.That(result, Is.EqualTo(FSharpValueOption.Some(25))); + } +} diff --git a/FruityFoundation.Tests.FsBaseInterop/FruityFoundation.Tests.FsBaseInterop.csproj b/FruityFoundation.Tests.FsBaseInterop/FruityFoundation.Tests.FsBaseInterop.csproj new file mode 100644 index 0000000..ccdfd9c --- /dev/null +++ b/FruityFoundation.Tests.FsBaseInterop/FruityFoundation.Tests.FsBaseInterop.csproj @@ -0,0 +1,34 @@ + + + + enable + enable + + false + true + net8.0;net6.0 + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + diff --git a/FruityFoundation.sln b/FruityFoundation.sln index a52733c..db789da 100644 --- a/FruityFoundation.sln +++ b/FruityFoundation.sln @@ -8,6 +8,12 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Db", "Db\Db.fsproj", "{500F EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsBase", "FsBase\FsBase.fsproj", "{41607026-96DC-4597-A3C4-E32008F8096F}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B44178DF-5B81-4029-90FA-2BF8E2A1EDBF}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FruityFoundation.Tests.FsBase", "FruityFoundation.Tests.FsBase\FruityFoundation.Tests.FsBase.fsproj", "{EBDC3640-4E47-43FE-BF0D-4BFFD07FE2EF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FruityFoundation.Tests.FsBaseInterop", "FruityFoundation.Tests.FsBaseInterop\FruityFoundation.Tests.FsBaseInterop.csproj", "{A64E73D3-EF87-4938-B01E-F9CC0B59F9DE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -30,5 +36,18 @@ Global {41607026-96DC-4597-A3C4-E32008F8096F}.Debug|Any CPU.Build.0 = Debug|Any CPU {41607026-96DC-4597-A3C4-E32008F8096F}.Release|Any CPU.ActiveCfg = Release|Any CPU {41607026-96DC-4597-A3C4-E32008F8096F}.Release|Any CPU.Build.0 = Release|Any CPU + {EBDC3640-4E47-43FE-BF0D-4BFFD07FE2EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EBDC3640-4E47-43FE-BF0D-4BFFD07FE2EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EBDC3640-4E47-43FE-BF0D-4BFFD07FE2EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EBDC3640-4E47-43FE-BF0D-4BFFD07FE2EF}.Release|Any CPU.Build.0 = Release|Any CPU + {A64E73D3-EF87-4938-B01E-F9CC0B59F9DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A64E73D3-EF87-4938-B01E-F9CC0B59F9DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A64E73D3-EF87-4938-B01E-F9CC0B59F9DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A64E73D3-EF87-4938-B01E-F9CC0B59F9DE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {50A75644-A1C3-4495-9DEB-DBB12D9334B5} = {B44178DF-5B81-4029-90FA-2BF8E2A1EDBF} + {EBDC3640-4E47-43FE-BF0D-4BFFD07FE2EF} = {B44178DF-5B81-4029-90FA-2BF8E2A1EDBF} + {A64E73D3-EF87-4938-B01E-F9CC0B59F9DE} = {B44178DF-5B81-4029-90FA-2BF8E2A1EDBF} EndGlobalSection EndGlobal diff --git a/FsBase/Extensions.fs b/FsBase/Extensions.fs index 6de5678..2dd6129 100644 --- a/FsBase/Extensions.fs +++ b/FsBase/Extensions.fs @@ -1,5 +1,6 @@ namespace FruityFoundation.FsBase open System.Collections.Generic +open System.Runtime.CompilerServices open FruityFoundation.Base.Structures module Array = @@ -13,3 +14,22 @@ module Option = let fromMaybe : Maybe<'a> -> 'a option = function | x when x.HasValue -> Some x.Value | _ -> None + +module ValueOption = + let toMaybe : 'a ValueOption -> Maybe<'a> = function + | ValueSome x -> x |> Maybe.Create + | ValueNone -> Maybe.Empty () + + let fromMaybe : Maybe<'a> -> 'a ValueOption = function + | x when x.HasValue -> ValueSome x.Value + | _ -> ValueNone + +type OptionMaybeInterop = + [] + static member ToMaybe (x : 'a option) = Option.toMaybe x + [] + static member ToMaybe (x : 'a ValueOption) = ValueOption.toMaybe x + [] + static member ToOption (x : 'a Maybe) = Option.fromMaybe x + [] + static member ToValueOption (x : 'a Maybe) = ValueOption.fromMaybe x diff --git a/FsBase/FsBase.fsproj b/FsBase/FsBase.fsproj index fd51650..b532f45 100644 --- a/FsBase/FsBase.fsproj +++ b/FsBase/FsBase.fsproj @@ -30,7 +30,7 @@ - +