tests
This commit is contained in:
parent
4917139553
commit
c3e1d26ab3
4 changed files with 104 additions and 13 deletions
|
@ -1,12 +1,86 @@
|
||||||
module Pentole.Result
|
namespace Pentole
|
||||||
|
|
||||||
type Result<'o, 'e> with
|
module Result =
|
||||||
|
|
||||||
|
let inline protect ([<InlineIfLambda>]f) x =
|
||||||
|
try
|
||||||
|
Ok (f x)
|
||||||
|
with e -> Error e
|
||||||
|
|
||||||
|
let inline pairwise_map fun_ (x: 'a, y: 'a) =
|
||||||
|
match fun_ x with
|
||||||
|
| Error e -> Error e
|
||||||
|
| Ok o ->
|
||||||
|
match fun_ y with | Ok o' -> Ok (o, o') | Error e -> Error e
|
||||||
|
|
||||||
|
let of_option = function | Some s -> Ok s | None -> Error ()
|
||||||
|
|
||||||
|
let zip a b =
|
||||||
|
match (a, b) with
|
||||||
|
| Ok a, Ok b -> Ok (a, b)
|
||||||
|
| Error e, _ -> Error e
|
||||||
|
| _, Error e -> Error e
|
||||||
|
|
||||||
|
module Unsafe =
|
||||||
|
/// <summary>
|
||||||
|
/// `o` if `Ok o` else throw
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
let inline get r =
|
||||||
|
match r with
|
||||||
|
| Ok o -> o
|
||||||
|
| Error e ->
|
||||||
|
$"Tried to access value from Result r, error={e}"
|
||||||
|
|> System.ArgumentException
|
||||||
|
|> raise
|
||||||
|
|
||||||
|
/// Module to operate on lists
|
||||||
|
module ResultList =
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// `o` if `Ok o` else throw
|
/// Transforms a sequence by applying a function that returns a Result, collecting successful results or short-circuiting on the first error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="result"></param>
|
///
|
||||||
static member get (result: Result<'o, 'e>) =
|
/// <param name="lambda">A function that transforms each element and returns a Result</param>
|
||||||
match result with
|
/// <param name="seq_">The input sequence to transform</param>
|
||||||
| Ok o -> o
|
/// <returns>
|
||||||
| Error e -> failwith $"Can't unwrap Error {e}"
|
/// <list>
|
||||||
|
/// - Ok of a list containing all successfully transformed elements if all transformations succeed
|
||||||
|
/// </list>
|
||||||
|
/// <list>
|
||||||
|
/// - Error with the first encountered error if any transformation fails
|
||||||
|
/// </list>
|
||||||
|
/// </returns>
|
||||||
|
/// <example>
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// <code>
|
||||||
|
/// let parseInts = ResultList.collect int "123,456,789".Split(',')
|
||||||
|
/// // Returns Ok [123; 456; 789]
|
||||||
|
/// </code>
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Error handling:
|
||||||
|
/// <code>
|
||||||
|
/// let parseInts = ResultList.collect (Result.protect int) ["123"; "abc"; "456"]
|
||||||
|
/// // Returns Error (FormatException "The input string 'abc' was not in a correct format.")
|
||||||
|
/// </code>
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Custom transformation:
|
||||||
|
///
|
||||||
|
/// <code>
|
||||||
|
/// let validatePositive x =
|
||||||
|
/// if x > 0 then Ok x else Error "Negative value"
|
||||||
|
/// let result = ResultList.collect validatePositive [1; 2; -3; 4]
|
||||||
|
/// // Returns Error "Negative value"
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
let collect (lambda: 'a -> Result<'ok, 'err>) (seq_: 'a seq) =
|
||||||
|
let rec iter_ acc seq_ =
|
||||||
|
match Seq.tryHead seq_ with
|
||||||
|
| None -> Ok acc
|
||||||
|
| Some x ->
|
||||||
|
match lambda x with
|
||||||
|
| Error e -> Error e
|
||||||
|
| Ok o -> iter_ (o::acc) (Seq.tail seq_)
|
||||||
|
iter_ [] seq_
|
||||||
|
|
|
@ -2,9 +2,9 @@ module Tests.Path
|
||||||
|
|
||||||
open NUnit.Framework
|
open NUnit.Framework
|
||||||
|
|
||||||
|
open Pentole
|
||||||
open Pentole.TestsExtensions
|
open Pentole.TestsExtensions
|
||||||
open Pentole.Path
|
open Pentole.Path
|
||||||
open Pentole.Result
|
|
||||||
|
|
||||||
[<Test>]
|
[<Test>]
|
||||||
let constructor_test () =
|
let constructor_test () =
|
||||||
|
@ -42,8 +42,8 @@ let resolve_test () =
|
||||||
s
|
s
|
||||||
|> Path.of_string
|
|> Path.of_string
|
||||||
|> Result.map FileSystem.resolve
|
|> Result.map FileSystem.resolve
|
||||||
|> Result.get
|
|> Result.Unsafe.get
|
||||||
let p (n: string ) = Path.of_string n |> Result.get
|
let p (n: string ) = Path.of_string n |> Result.Unsafe.get
|
||||||
|
|
||||||
"/" |> test |> Assert.ok_is_equal (p "/")
|
"/" |> test |> Assert.ok_is_equal (p "/")
|
||||||
"/etc/../" |> test |> Assert.ok_is_equal (p "/")
|
"/etc/../" |> test |> Assert.ok_is_equal (p "/")
|
||||||
|
@ -51,7 +51,7 @@ let resolve_test () =
|
||||||
|
|
||||||
[<Test>]
|
[<Test>]
|
||||||
let equality_test () =
|
let equality_test () =
|
||||||
let p (n: string ) = Path.of_string n |> Result.get
|
let p (n: string ) = Path.of_string n |> Result.Unsafe.get
|
||||||
Assert.are_equal (p "/etc") (p "/etc/")
|
Assert.are_equal (p "/etc") (p "/etc/")
|
||||||
(*
|
(*
|
||||||
[<Test>]
|
[<Test>]
|
||||||
|
|
16
tests/result_tests.fs
Normal file
16
tests/result_tests.fs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
module Tests.Result
|
||||||
|
|
||||||
|
open NUnit.Framework
|
||||||
|
|
||||||
|
open Pentole.TestsExtensions
|
||||||
|
|
||||||
|
open Pentole
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let err_test () =
|
||||||
|
let got = ResultList.collect (Result.protect int) ["123"; "abc"; "456"]
|
||||||
|
let msg = "The input string 'abc' was not in a correct format."
|
||||||
|
|
||||||
|
match got with
|
||||||
|
| Ok _ -> Assert.Fail "Expected an error"
|
||||||
|
| Error exn -> Assert.are_equal exn.Message msg
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="bytes_tests.fs" />
|
<Compile Include="bytes_tests.fs" />
|
||||||
|
<Compile Include="result_tests.fs" />
|
||||||
<Compile Include="string_tests.fs" />
|
<Compile Include="string_tests.fs" />
|
||||||
<Compile Include="path_tests.fs" />
|
<Compile Include="path_tests.fs" />
|
||||||
<Compile Include="Program.fs" />
|
<Compile Include="Program.fs" />
|
||||||
|
|
Loading…
Reference in a new issue