Skip to content

Instantly share code, notes, and snippets.

@fotonmoton
Created November 19, 2019 19:23
Show Gist options
  • Save fotonmoton/72e971692a66702dc260453703248130 to your computer and use it in GitHub Desktop.
Save fotonmoton/72e971692a66702dc260453703248130 to your computer and use it in GitHub Desktop.
module BankAccount
type Account = decimal option ref
let mkBankAccount(): Account = ref None
let openAccount (account: Account): Account =
account := Some 0m
account
let closeAccount account =
account := None
account
let getBalance account = !account
let updateBalance (change: decimal) (account: Account) =
lock account (fun () ->
match !account with
| None -> account := Some change
| Some balance -> account := Some (balance + change))
account
// This file was created manually and its version is 2.0.0.
module BankAccountTest
open Xunit
open FsUnit.Xunit
open BankAccount
[<Fact>]
let ``Returns empty balance after opening`` () =
let account = mkBankAccount() |> openAccount
getBalance account |> should equal (Some 0.0m)
[<Fact>]
let ``Check basic balance`` () =
let account = mkBankAccount() |> openAccount
let openingBalance = account |> getBalance
let updatedBalance =
account
|> updateBalance 10.0m
|> getBalance
openingBalance |> should equal (Some 0.0m)
updatedBalance |> should equal (Some 10.0m)
[<Fact>]
let ``Balance can increment or decrement`` () =
let account = mkBankAccount() |> openAccount
let openingBalance = account |> getBalance
let addedBalance =
account
|> updateBalance 10.0m
|> getBalance
let subtractedBalance =
account
|> updateBalance -15.0m
|> getBalance
openingBalance |> should equal (Some 0.0m)
addedBalance |> should equal (Some 10.0m)
subtractedBalance |> should equal (Some -5.0m)
[<Fact>]
let ``Account can be closed`` () =
let account =
mkBankAccount()
|> openAccount
|> closeAccount
getBalance account |> should equal None
account |> should not' (equal None)
[<Fact>]
let ``Account can be updated from multiple threads`` () =
let account =
mkBankAccount()
|> openAccount
let updateAccountAsync =
async {
account
|> updateBalance 1.0m
|> ignore
}
updateAccountAsync
|> List.replicate 1000
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
getBalance account |> should equal (Some 1000.0m)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment