diff --git a/src/Fable.Cli/CHANGELOG.md b/src/Fable.Cli/CHANGELOG.md index e50f58253..49082ec7c 100644 --- a/src/Fable.Cli/CHANGELOG.md +++ b/src/Fable.Cli/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed * [Rust] Fixed derived traits mapping (by @ncave) +* [JS/TS] Added missing ICollection helpers (#3914) (by @ncave) ## 4.23.0 - 2024-10-28 diff --git a/src/Fable.Transforms/Replacements.fs b/src/Fable.Transforms/Replacements.fs index d3f19c259..2ec0501a6 100644 --- a/src/Fable.Transforms/Replacements.fs +++ b/src/Fable.Transforms/Replacements.fs @@ -1790,6 +1790,10 @@ let injectIndexOfArgs com ctx r genArgs args = injectArg com ctx r "Array" "indexOf" genArgs args +let copyToArray (com: ICompiler) r t (i: CallInfo) args = + Helper.LibCall(com, "Util", "copyToArray", t, args, i.SignatureArgTypes, genArgs = i.GenericArgs, ?loc = r) + |> Some + let resizeArrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) = match i.CompiledName, thisArg, args with | ".ctor", _, [] -> makeResizeArray (getElementType t) [] |> Some @@ -1803,6 +1807,13 @@ let resizeArrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (this |> Some | "get_Item", Some ar, [ idx ] -> getExpr r t ar idx |> Some | "set_Item", Some ar, [ idx; value ] -> setExpr r ar idx value |> Some + | "CopyTo", Some ar, [ target ] -> + let count = getFieldWith r t ar "length" + copyToArray com r t i [ ar; makeIntConst 0; target; makeIntConst 0; count ] + | "CopyTo", Some ar, [ target; targetIndex ] -> + let count = getFieldWith r t ar "length" + copyToArray com r t i [ ar; makeIntConst 0; target; targetIndex; count ] + | "CopyTo", Some ar, [ _sourceIndex; _target; _targetIndex; _count ] -> copyToArray com r t i (ar :: args) | "Add", Some ar, [ arg ] -> "void ($0)" |> emitExpr r t [ Helper.InstanceCall(ar, "push", t, [ arg ]) ] @@ -1942,10 +1953,6 @@ let tuples (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: E | "ToTuple", _ -> changeKind false args | _ -> None -let copyToArray (com: ICompiler) r t (i: CallInfo) args = - Helper.LibCall(com, "Util", "copyToArray", t, args, i.SignatureArgTypes, genArgs = i.GenericArgs, ?loc = r) - |> Some - let arrays (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) = match i.CompiledName, thisArg, args with | "get_Length", Some arg, _ -> getFieldWith r t arg "length" |> Some @@ -2649,6 +2656,11 @@ let dictionaries (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Exp makeComparerFromEqualityComparer eqComp |> makeDictionaryWithComparer com r t arg |> Some + | [ IEnumerable ], [ arg ] -> makeDictionary com ctx r t arg |> Some + | [ IEnumerable; IEqualityComparer ], [ arg; eqComp ] -> + makeComparerFromEqualityComparer eqComp + |> makeDictionaryWithComparer com r t arg + |> Some | [ IEqualityComparer ], [ eqComp ] | [ Number _; IEqualityComparer ], [ _; eqComp ] -> makeComparerFromEqualityComparer eqComp @@ -2680,6 +2692,13 @@ let dictionaries (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Exp Some c -> Helper.InstanceCall(c, methName, t, args, i.SignatureArgTypes, ?loc = r) |> Some | _ -> None +let collections (com: ICompiler) (ctx: Context) r (t: Type) (i: CallInfo) (thisArg: Expr option) (args: Expr list) = + match i.CompiledName, thisArg with + | ("get_Count" | "get_IsReadOnly" | "Add" | "Remove" | "Clear" | "Contains" | "CopyTo") as meth, Some ar -> + let meth = Naming.removeGetSetPrefix meth |> Naming.lowerFirst + Helper.LibCall(com, "CollectionUtil", meth, t, ar :: args, ?loc = r) |> Some + | _ -> None + let conditionalWeakTable (com: ICompiler) (ctx: Context) r t (i: CallInfo) (thisArg: Expr option) (args: Expr list) = match i.CompiledName, thisArg with | ".ctor", _ -> @@ -3975,8 +3994,8 @@ let private replacedModules = Types.resizeArray, resizeArrays "System.Collections.Generic.IList`1", resizeArrays "System.Collections.IList", resizeArrays - Types.icollectionGeneric, resizeArrays - Types.icollection, resizeArrays + Types.icollectionGeneric, collections + Types.icollection, collections "System.Collections.Generic.CollectionExtensions", collectionExtensions "System.ReadOnlySpan`1", readOnlySpans Types.hashset, hashSets diff --git a/src/fable-library-ts/CollectionUtil.ts b/src/fable-library-ts/CollectionUtil.ts new file mode 100644 index 000000000..70f693809 --- /dev/null +++ b/src/fable-library-ts/CollectionUtil.ts @@ -0,0 +1,134 @@ +import { equals, isArrayLike } from "./Util.js"; + +export function count(col: Iterable): number { + if (typeof (col as any)["System.Collections.Generic.ICollection`1.get_Count"] === "function") { + return (col as any)["System.Collections.Generic.ICollection`1.get_Count"](); // collection + } else { + if (isArrayLike(col)) { + return col.length; // resize array + } else { + if (typeof (col as any).size === "number") { + return (col as any).size; // map, set + } else { + let count = 0; + for (const _ of col) { + count++; + } + return count; + } + } + } +} + +export function isReadOnly(col: Iterable): boolean { + if (typeof (col as any)["System.Collections.Generic.ICollection`1.get_IsReadOnly"] === "function") { + return (col as any)["System.Collections.Generic.ICollection`1.get_IsReadOnly"](); // collection + } else { + return false; + } +} + +export function copyTo(col: Iterable, array: T[], arrayIndex: number) { + if (typeof (col as any)["System.Collections.Generic.ICollection`1.CopyToZ3B4C077E"] === "function") { + (col as any)["System.Collections.Generic.ICollection`1.CopyToZ3B4C077E"](array, arrayIndex); // collection + } else { + let i = arrayIndex; + for (const v of col) { + array[i] = v; + i++; + } + } +} + +export function contains(col: Iterable, item: T): boolean { + if (typeof (col as any)["System.Collections.Generic.ICollection`1.Contains2B595"] === "function") { + return (col as any)["System.Collections.Generic.ICollection`1.Contains2B595"](item); // collection + } else { + if (isArrayLike(col)) { + let i = col.findIndex(x => equals(x, item)); // resize array + return i >= 0; + } else { + if (typeof (col as any).has === "function") { + if (typeof (col as any).set === "function" && isArrayLike(item)) { + return (col as any).has(item[0]) && equals((col as any).get(item[0]), item[1]); // map + } else { + return (col as any).has(item); // set + } + } else { + return false; // unknown collection + } + } + } +} + +export function add(col: Iterable, item: T): void { + if (typeof (col as any)["System.Collections.Generic.ICollection`1.Add2B595"] === "function") { + return (col as any)["System.Collections.Generic.ICollection`1.Add2B595"](item); // collection + } else { + if (isArrayLike(col)) { + col.push(item); // resize array + } else { + if (typeof (col as any).add === "function") { + return (col as any).add(item); // set + } else { + if (typeof (col as any).has === "function" + && typeof (col as any).set === "function" + && isArrayLike(item)) { + if ((col as any).has(item[0]) === false) { + (col as any).set(item[0], item[1]); // map + } else { + throw new Error("An item with the same key has already been added. Key: " + item[0]); + } + } else { + // unknown collection + } + } + } + } +} + +export function remove(col: Iterable, item: T): boolean { + if (typeof (col as any)["System.Collections.Generic.ICollection`1.Remove2B595"] === "function") { + return (col as any)["System.Collections.Generic.ICollection`1.Remove2B595"](item); // collection + } else { + if (isArrayLike(col)) { + let i = col.findIndex(x => equals(x, item)); + if (i >= 0) { + col.splice(i, 1); // resize array + return true; + } else { + return false; + } + } else { + if (typeof (col as any).delete === "function") { + if (typeof (col as any).set === "function" && isArrayLike(item)) { + if ((col as any).has(item[0]) && equals((col as any).get(item[0]), item[1])) { + return (col as any).delete(item[0]); // map + } else { + return false; + } + } else { + return (col as any).delete(item); // set + } + } else { + return false; // unknown collection + } + } + } +} + +export function clear(col: Iterable): void { + if (typeof (col as any)["System.Collections.Generic.ICollection`1.Clear"] === "function") { + return (col as any)["System.Collections.Generic.ICollection`1.Clear"](); // collection + } else { + if (isArrayLike(col)) { + col.splice(0); // resize array + } else { + if (typeof (col as any).clear === "function") { + (col as any).clear(); // map, set + } else { + // unknown collection + } + } + } +} \ No newline at end of file diff --git a/tests/Dart/src/ArrayTests.fs b/tests/Dart/src/ArrayTests.fs index dba3f2a9d..3a20dea33 100644 --- a/tests/Dart/src/ArrayTests.fs +++ b/tests/Dart/src/ArrayTests.fs @@ -1,10 +1,9 @@ module Fable.Tests.Dart.Array -open System open Util type ParamArrayTest = - static member Add([] xs: int[]) = Array.sum xs + static member Add([] xs: int[]) = Array.sum xs let add (xs: int[]) = ParamArrayTest.Add(xs) @@ -312,7 +311,7 @@ let tests () = // TODO: Char.IsLetter // testCase "Array.filter with chars works" <| fun () -> // let xs = [|'a'; '2'; 'b'; 'c'|] - // let ys = xs |> Array.filter Char.IsLetter + // let ys = xs |> Array.filter System.Char.IsLetter // ys.Length |> equal 3 testCase "Array.find works" <| fun () -> @@ -960,16 +959,16 @@ let tests () = ys :? System.Array |> equal true zs :? System.Array |> equal false - testCase "Array.Copy works with numeric arrays" <| fun () -> + testCase "System.Array.Copy works with numeric arrays" <| fun () -> let source = [| 99 |] let destination = [| 1; 2; 3 |] - Array.Copy(source, 0, destination, 0, 1) + System.Array.Copy(source, 0, destination, 0, 1) equal [| 99; 2; 3 |] destination - testCase "Array.Copy works with non-numeric arrays" <| fun () -> + testCase "System.Array.Copy works with non-numeric arrays" <| fun () -> let source = [| "xy"; "xx"; "xyz" |] let destination = [| "a"; "b"; "c" |] - Array.Copy(source, 1, destination, 1, 2) + System.Array.Copy(source, 1, destination, 1, 2) equal [| "a"; "xx"; "xyz" |] destination testCase "Array.splitInto works" <| fun () -> @@ -1102,3 +1101,30 @@ let tests () = throwsAnyError (fun () -> Array.removeManyAt 0 2 [||] |> ignore) throwsAnyError (fun () -> Array.removeManyAt -1 2 [|1|] |> ignore) throwsAnyError (fun () -> Array.removeManyAt 2 2 [|1|] |> ignore) + + // testCase "Array.compareWith works" <| fun () -> // See #2961 + // let a = [|1;3|] + // let b = [|1;2;3|] + // // compares lengths first, then elements + // let c1 = a < b + // let c2 = compare a b + // // should compare elements first, then lengths + // let c3 = Array.compareWith compare a b + // equal c1 true + // equal c2 -1 + // equal c3 1 + + // testCase "System.Array.Resize works" <| fun () -> + // let mutable xs = [|1; 2; 3; 4; 5|] + // System.Array.Resize(&xs, 3) + // xs |> equal [|1; 2; 3|] + // System.Array.Resize(&xs, 7) + // xs |> equal [|1; 2; 3; 0; 0; 0; 0|] + // System.Array.Resize(&xs, 0) + // xs |> equal [||] + // xs <- null + // System.Array.Resize(&xs, 3) + // xs |> equal [|0; 0; 0|] + // xs <- null + // System.Array.Resize(&xs, 0) + // xs |> equal [||] diff --git a/tests/Dart/src/ListTests.fs b/tests/Dart/src/ListTests.fs index b268674ea..feffd8501 100644 --- a/tests/Dart/src/ListTests.fs +++ b/tests/Dart/src/ListTests.fs @@ -70,290 +70,290 @@ let tests() = |> equal 1 testCase "List.Length works" <| fun () -> - let xs = [1; 2; 3; 4] - equal 4 xs.Length - equal 0 [].Length + let xs = [1; 2; 3; 4] + equal 4 xs.Length + equal 0 [].Length testCase "List.IsEmpty works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys: int list = [] - equal false xs.IsEmpty - equal false [1; 2; 3; 4].IsEmpty - equal true ys.IsEmpty - equal true [].IsEmpty + let xs = [1; 2; 3; 4] + let ys: int list = [] + equal false xs.IsEmpty + equal false [1; 2; 3; 4].IsEmpty + equal true ys.IsEmpty + equal true [].IsEmpty testCase "List.Equals works" <| fun () -> - let xs = [1;2;3] - xs.Equals(xs) |> equal true + let xs = [1;2;3] + xs.Equals(xs) |> equal true testCase "List.Head works" <| fun () -> - let xs = [1; 2; 3; 4] - equal 1 xs.Head + let xs = [1; 2; 3; 4] + equal 1 xs.Head testCase "List.Tail works" <| fun () -> - let xs = [1; 2; 3; 4] - equal 2 xs.Tail.Head + let xs = [1; 2; 3; 4] + equal 2 xs.Tail.Head testCase "List.Item works" <| fun () -> - let xs = [1; 2; 3; 4] - equal 4 xs.[3] + let xs = [1; 2; 3; 4] + equal 4 xs.[3] testCase "List cons works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = 3 :: xs - let zs = List.Cons(4, xs) - ys.Head + xs.Head - |> equal zs.Head + let xs = [1; 2; 3; 4] + let ys = 3 :: xs + let zs = List.Cons(4, xs) + ys.Head + xs.Head + |> equal zs.Head testCase "List.cons works II" <| fun () -> - let li = [1;2;3;4;5] - let li2 = li.Tail - let li3 = [8;9;11] @ li2 - let li3b = [20;16] @ li3.Tail - let li4 = 14 :: li3b - li4.[1] |> equal 20 - li4.[3] |> equal 9 - List.length li4 |> equal 9 - List.sum li4 |> equal 84 + let li = [1;2;3;4;5] + let li2 = li.Tail + let li3 = [8;9;11] @ li2 + let li3b = [20;16] @ li3.Tail + let li4 = 14 :: li3b + li4.[1] |> equal 20 + li4.[3] |> equal 9 + List.length li4 |> equal 9 + List.sum li4 |> equal 84 testCase "List.empty works" <| fun () -> - let xs = 1 :: List.Empty - let ys = 1 :: List.empty - xs.Length + ys.Length |> equal 2 + let xs = 1 :: List.Empty + let ys = 1 :: List.empty + xs.Length + ys.Length |> equal 2 testCase "List.append works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [0] - let zs = List.append ys xs - zs.Head + zs.Tail.Head - |> equal 1 + let xs = [1; 2; 3; 4] + let ys = [0] + let zs = List.append ys xs + zs.Head + zs.Tail.Head + |> equal 1 testCase "List.append works II" <| fun () -> - let li = [1;2;3;4;5] - let li2 = li.Tail - let li3 = [8;9;11] @ li2 - let li3b = [20;16] @ li3.Tail - let li4 = li3b @ li2 - li4.[1] |> equal 16 - li4.[9] |> equal 3 - List.length li4 |> equal 12 - List.sum li4 |> equal 84 + let li = [1;2;3;4;5] + let li2 = li.Tail + let li3 = [8;9;11] @ li2 + let li3b = [20;16] @ li3.Tail + let li4 = li3b @ li2 + li4.[1] |> equal 16 + li4.[9] |> equal 3 + List.length li4 |> equal 12 + List.sum li4 |> equal 84 testCase "List.append works with empty list" <| fun () -> - let li = [{ Bar = "2" }; { Bar = "4" };] - let li = li @ [] - let li = [] @ li - li - |> Seq.map (fun x -> 20 / int x.Bar) - |> Seq.sum - |> equal 15 + let li = [{ Bar = "2" }; { Bar = "4" };] + let li = li @ [] + let li = [] @ li + li + |> Seq.map (fun x -> 20 / int x.Bar) + |> Seq.sum + |> equal 15 testCase "List.choose works" <| fun () -> - let xs = [1; 2; 3; 4] - let result = xs |> List.choose (fun x -> - if x > 2 then Some x - else None) - result.Head + result.Tail.Head - |> equal 7 + let xs = [1; 2; 3; 4] + let result = xs |> List.choose (fun x -> + if x > 2 then Some x + else None) + result.Head + result.Tail.Head + |> equal 7 testCase "List.exactlyOne works" <| fun () -> - let xs = [1.;] - xs |> List.exactlyOne - |> equal 1. + let xs = [1.;] + xs |> List.exactlyOne + |> equal 1. - let xs2 = [1.;2.] - (try List.exactlyOne xs2 |> ignore; false with | _ -> true) |> equal true + let xs2 = [1.;2.] + (try List.exactlyOne xs2 |> ignore; false with | _ -> true) |> equal true - let xs3: int list = [] - (try List.exactlyOne xs3 |> ignore; false with | _ -> true) |> equal true + let xs3: int list = [] + (try List.exactlyOne xs3 |> ignore; false with | _ -> true) |> equal true testCase "List.tryExactlyOne works" <| fun () -> - [1.] |> List.tryExactlyOne |> equal (Some 1.) - [1.;2.] |> List.tryExactlyOne |> equal None - [] |> List.tryExactlyOne |> equal None + [1.] |> List.tryExactlyOne |> equal (Some 1.) + [1.;2.] |> List.tryExactlyOne |> equal None + [] |> List.tryExactlyOne |> equal None testCase "List.exists works" <| fun () -> - let xs = [1; 2; 3; 4] - xs |> List.exists (fun x -> x = 2) - |> equal true + let xs = [1; 2; 3; 4] + xs |> List.exists (fun x -> x = 2) + |> equal true testCase "List.exists2 works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [1; 2; 3; 4] - List.exists2 (fun x y -> x * y = 16) xs ys - |> equal true + let xs = [1; 2; 3; 4] + let ys = [1; 2; 3; 4] + List.exists2 (fun x y -> x * y = 16) xs ys + |> equal true testCase "List.filter works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = xs |> List.filter (fun x -> x > 5) - equal ys.IsEmpty true + let xs = [1; 2; 3; 4] + let ys = xs |> List.filter (fun x -> x > 5) + equal ys.IsEmpty true testCase "List.filter doesn't work backwards" <| fun () -> // See #1672 - let li = [1; 2; 3; 4; 5] - li |> List.filteri (fun i _ -> i <> 1) |> equal [1; 3; 4; 5] + let li = [1; 2; 3; 4; 5] + li |> List.filteri (fun i _ -> i <> 1) |> equal [1; 3; 4; 5] testCase "List.find works" <| fun () -> - [1; 2; 3; 4] - |> List.find ((=) 2) - |> equal 2 + [1; 2; 3; 4] + |> List.find ((=) 2) + |> equal 2 testCase "List.findIndex works" <| fun () -> - [1; 2; 3; 4] - |> List.findIndex ((=) 2) - |> equal 1 + [1; 2; 3; 4] + |> List.findIndex ((=) 2) + |> equal 1 testCase "List.fold works" <| fun () -> - [1; 2; 3; 4] - |> List.fold (+) 0 - |> equal 10 + [1; 2; 3; 4] + |> List.fold (+) 0 + |> equal 10 testCase "List.fold2 works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [1; 2; 3; 4] - List.fold2 (fun x y z -> x + y + z) 0 xs ys - |> equal 20 + let xs = [1; 2; 3; 4] + let ys = [1; 2; 3; 4] + List.fold2 (fun x y z -> x + y + z) 0 xs ys + |> equal 20 testCase "List.foldBack works" <| fun () -> - [1; 2; 3; 4] - |> List.foldBack (fun x acc -> acc - x) <| 100 - |> equal 90 + [1; 2; 3; 4] + |> List.foldBack (fun x acc -> acc - x) <| 100 + |> equal 90 testCase "List.foldBack with composition works" <| fun () -> - [1; 2; 3; 4] - |> List.foldBack (fun x acc -> acc >> (+) x) <| id <| 2 - |> equal 12 + [1; 2; 3; 4] + |> List.foldBack (fun x acc -> acc >> (+) x) <| id <| 2 + |> equal 12 testCase "List.forall works" <| fun () -> - [1; 2; 3; 4] - |> List.forall (fun x -> x < 5) - |> equal true + [1; 2; 3; 4] + |> List.forall (fun x -> x < 5) + |> equal true testCase "List.forall2 works" <| fun () -> - ([1; 2; 3; 4], [1; 2; 3; 4]) - ||> List.forall2 (=) - |> equal true + ([1; 2; 3; 4], [1; 2; 3; 4]) + ||> List.forall2 (=) + |> equal true testCase "List.head works" <| fun () -> - [1; 2; 3; 4] - |> List.head - |> equal 1 + [1; 2; 3; 4] + |> List.head + |> equal 1 testCase "List.init works" <| fun () -> - let xs = List.init 4 float - xs.Head + xs.Tail.Head - |> equal 1. + let xs = List.init 4 float + xs.Head + xs.Tail.Head + |> equal 1. testCase "List.isEmpty works" <| fun () -> - List.isEmpty [1] |> equal false - List.isEmpty [] |> equal true + List.isEmpty [1] |> equal false + List.isEmpty [] |> equal true testCase "List.iter works" <| fun () -> - let xs = [1; 2; 3; 4] - let mutable total = 0 - xs |> List.iter (fun x -> - total <- total + x) - equal 10 total + let xs = [1; 2; 3; 4] + let mutable total = 0 + xs |> List.iter (fun x -> + total <- total + x) + equal 10 total testCase "List.iter2 works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [2; 4; 6; 8] - let mutable total = 0 - List.iter2 (fun x y -> total <- total + (y - x)) xs ys - equal 10 total + let xs = [1; 2; 3; 4] + let ys = [2; 4; 6; 8] + let mutable total = 0 + List.iter2 (fun x y -> total <- total + (y - x)) xs ys + equal 10 total testCase "List.iteri works" <| fun () -> - let mutable total = 0 - [1; 2; 3; 4] - |> List.iteri (fun i x -> - total <- total + (i * x)) - equal 20 total + let mutable total = 0 + [1; 2; 3; 4] + |> List.iteri (fun i x -> + total <- total + (i * x)) + equal 20 total testCase "List.iteri2 works" <| fun () -> - let mutable total = 0 - let xs = [1; 2; 3; 4] - let ys = [2; 4; 6; 8] - List.iteri2 (fun i x y -> - total <- total + i * (y - x) - ) xs ys - equal 20 total + let mutable total = 0 + let xs = [1; 2; 3; 4] + let ys = [2; 4; 6; 8] + List.iteri2 (fun i x y -> + total <- total + i * (y - x) + ) xs ys + equal 20 total testCase "List.length works" <| fun () -> - let xs = [1; 2; 3; 4] - List.length xs - |> equal 4 + let xs = [1; 2; 3; 4] + List.length xs + |> equal 4 testCase "List.item works" <| fun () -> - [1; 2] |> List.item 1 |> equal 2 + [1; 2] |> List.item 1 |> equal 2 testCase "List.map works" <| fun () -> - let xs = [1;2;3] - let ys = xs |> List.map ((*) 2) - equal 4 ys.Tail.Head + let xs = [1;2;3] + let ys = xs |> List.map ((*) 2) + equal 4 ys.Tail.Head testCase "List.mapi works" <| fun () -> - let xs = [1] - let ys = xs |> List.mapi (fun i x -> i * x) - equal 0 ys.Head + let xs = [1] + let ys = xs |> List.mapi (fun i x -> i * x) + equal 0 ys.Head testCase "List.map2 works" <| fun () -> - let xs = [1;2] - let ys = [2;3] - let zs = List.map2 (fun x y -> x - y) xs ys - equal -1 zs.Head + let xs = [1;2] + let ys = [2;3] + let zs = List.map2 (fun x y -> x - y) xs ys + equal -1 zs.Head testCase "List.ofArray works" <| fun () -> - let xs = [|1; 2|] - let ys = List.ofArray xs - ys.Head |> equal 1 + let xs = [|1; 2|] + let ys = List.ofArray xs + ys.Head |> equal 1 - let xs1 = [|1.; 2.; 3.; 4.|] - let ys1 = List.ofArray xs1 - sumFirstList ys1 3 |> equal 6. + let xs1 = [|1.; 2.; 3.; 4.|] + let ys1 = List.ofArray xs1 + sumFirstList ys1 3 |> equal 6. testCase "List.ofSeq works" <| fun () -> - // let xs = [|1; 2|] :> _ seq - let ys = List.ofSeq <| seq { yield 1; yield 2 } - ys.Head |> equal 1 - ys.Length |> equal 2 + // let xs = [|1; 2|] :> _ seq + let ys = List.ofSeq <| seq { yield 1; yield 2 } + ys.Head |> equal 1 + ys.Length |> equal 2 testCase "List.pick works" <| fun () -> - let xs = [1; 2] - xs |> List.pick (fun x -> - match x with - | 2 -> Some x - | _ -> None) - |> equal 2 + let xs = [1; 2] + xs |> List.pick (fun x -> + match x with + | 2 -> Some x + | _ -> None) + |> equal 2 testCase "List.reduce works" <| fun () -> - let xs = [1; 2] - xs |> List.reduce (+) - |> equal 3 + let xs = [1; 2] + xs |> List.reduce (+) + |> equal 3 testCase "List.reduceBack works" <| fun () -> - let xs = [1; 2] - xs |> List.reduceBack (+) - |> equal 3 + let xs = [1; 2] + xs |> List.reduceBack (+) + |> equal 3 testCase "List.replicate works" <| fun () -> - List.replicate 3 3 - |> List.sum |> equal 9 + List.replicate 3 3 + |> List.sum |> equal 9 testCase "List.rev works" <| fun () -> - let xs = [1; 2; 3] - let ys = xs |> List.rev - equal 3 ys.Head + let xs = [1; 2; 3] + let ys = xs |> List.rev + equal 3 ys.Head testCase "List.scan works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = (0, xs) ||> List.scan (fun acc x -> acc - x) - ys.[3] + ys.[4] - |> equal -16 + let xs = [1; 2; 3; 4] + let ys = (0, xs) ||> List.scan (fun acc x -> acc - x) + ys.[3] + ys.[4] + |> equal -16 testCase "List.scanBack works" <| fun () -> - let xs = [1; 2; 3] - let ys = List.scanBack (fun x acc -> acc - x) xs 0 - ys.Head + ys.Tail.Head - |> equal -11 + let xs = [1; 2; 3] + let ys = List.scanBack (fun x acc -> acc - x) xs 0 + ys.Head + ys.Tail.Head + |> equal -11 testCase "List.sort works" <| fun () -> let xs = [3; 4; 1; -3; 2; 10] @@ -391,47 +391,47 @@ let tests() = |> equal 3 testCase "List.max works" <| fun () -> - let xs = [1; 2] - xs |> List.max - |> equal 2 + let xs = [1; 2] + xs |> List.max + |> equal 2 testCase "List.maxBy works" <| fun () -> - let xs = [1; 2] - xs |> List.maxBy (fun x -> -x) - |> equal 1 + let xs = [1; 2] + xs |> List.maxBy (fun x -> -x) + |> equal 1 testCase "List.min works" <| fun () -> - let xs = [1; 2] - xs |> List.min - |> equal 1 + let xs = [1; 2] + xs |> List.min + |> equal 1 testCase "List.minBy works" <| fun () -> - let xs = [1; 2] - xs |> List.minBy (fun x -> -x) - |> equal 2 + let xs = [1; 2] + xs |> List.minBy (fun x -> -x) + |> equal 2 testCase "List.sum works" <| fun () -> - [1; 2] |> List.sum - |> equal 3 + [1; 2] |> List.sum + |> equal 3 testCase "List.sumBy works" <| fun () -> - [1; 2] |> List.sumBy (fun x -> x*2) - |> equal 6 + [1; 2] |> List.sumBy (fun x -> x*2) + |> equal 6 testCase "List.sum with non numeric types works" <| fun () -> - let p1 = {x=1; y=10} - let p2 = {x=2; y=20} - [p1; p2] |> List.sum |> (=) {x=3;y=30} |> equal true + let p1 = {x=1; y=10} + let p2 = {x=2; y=20} + [p1; p2] |> List.sum |> (=) {x=3;y=30} |> equal true testCase "List.sumBy with non numeric types works" <| fun () -> - let p1 = {x=1; y=10} - let p2 = {x=2; y=20} - [p1; p2] |> List.sumBy Point.Neg |> (=) {x = -3; y = -30} |> equal true + let p1 = {x=1; y=10} + let p2 = {x=2; y=20} + [p1; p2] |> List.sumBy Point.Neg |> (=) {x = -3; y = -30} |> equal true testCase "List.sumBy with numeric projection works" <| fun () -> - let p1 = {x=1; y=10} - let p2 = {x=2; y=20} - [p1; p2] |> List.sumBy (fun p -> p.y) |> equal 30 + let p1 = {x=1; y=10} + let p2 = {x=2; y=20} + [p1; p2] |> List.sumBy (fun p -> p.y) |> equal 30 testCase "List.sum with non numeric types works II" <| fun () -> [MyNumber 1; MyNumber 2; MyNumber 3] |> List.sum |> equal (MyNumber 6) @@ -468,142 +468,142 @@ let tests() = |> equal 2. testCase "List.tail works" <| fun () -> - let xs = [1; 2] - let ys = xs |> List.tail - equal 1 ys.Length + let xs = [1; 2] + let ys = xs |> List.tail + equal 1 ys.Length testCase "List.toArray works" <| fun () -> - let ys = List.toArray [1; 2] - ys.[0] + ys.[1] |> equal 3 - let xs = [1; 1] - let ys2 = List.toArray (2::xs) - ys2.[0] + ys2.[1] + ys2.[2] |> equal 4 + let ys = List.toArray [1; 2] + ys.[0] + ys.[1] |> equal 3 + let xs = [1; 1] + let ys2 = List.toArray (2::xs) + ys2.[0] + ys2.[1] + ys2.[2] |> equal 4 testCase "List.toSeq works" <| fun () -> - [1; 2] - |> List.toSeq - |> Seq.tail |> Seq.head - |> equal 2 + [1; 2] + |> List.toSeq + |> Seq.tail |> Seq.head + |> equal 2 testCase "List.tryPick works" <| fun () -> - [1; 2] - |> List.tryPick (function - | 2 -> Some 2 - | _ -> None) - |> function - | Some x -> x - | None -> 0 - |> equal 2 + [1; 2] + |> List.tryPick (function + | 2 -> Some 2 + | _ -> None) + |> function + | Some x -> x + | None -> 0 + |> equal 2 testCase "List.tryFind works" <| fun () -> - [1; 2] - |> List.tryFind ((=) 5) - |> equal None + [1; 2] + |> List.tryFind ((=) 5) + |> equal None testCase "List.tryFindIndex works" <| fun () -> - let xs = [1; 2] - let ys = xs |> List.tryFindIndex ((=) 2) - ys |> equal (Some 1) - xs |> List.tryFindIndex ((=) 5) |> equal None + let xs = [1; 2] + let ys = xs |> List.tryFindIndex ((=) 2) + ys |> equal (Some 1) + xs |> List.tryFindIndex ((=) 5) |> equal None testCase "List.unzip works" <| fun () -> - let xs = [1, 2] - let ys, zs = xs |> List.unzip - ys.Head + zs.Head - |> equal 3 + let xs = [1, 2] + let ys, zs = xs |> List.unzip + ys.Head + zs.Head + |> equal 3 testCase "List.unzip3 works" <| fun () -> - let xs = [(1, 2, 3); (4, 5, 6)] - let ys, zs, ks = xs |> List.unzip3 - ys.[1] + zs.[1] + ks.[1] - |> equal 15 + let xs = [(1, 2, 3); (4, 5, 6)] + let ys, zs, ks = xs |> List.unzip3 + ys.[1] + zs.[1] + ks.[1] + |> equal 15 testCase "List.zip works" <| fun () -> - let xs = [1; 2; 3] - let ys = [4; 5; 6] - let zs = List.zip xs ys - let x, y = zs.Tail.Head - equal 2 x - equal 5 y + let xs = [1; 2; 3] + let ys = [4; 5; 6] + let zs = List.zip xs ys + let x, y = zs.Tail.Head + equal 2 x + equal 5 y testCase "List snail to append works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [0] - let zs = ys @ xs - zs.Head + zs.Tail.Head - |> equal 1 + let xs = [1; 2; 3; 4] + let ys = [0] + let zs = ys @ xs + zs.Head + zs.Tail.Head + |> equal 1 testCase "List slice works" <| fun () -> - let xs = [1; 2; 3; 4] - xs.[..2] |> List.sum |> equal 6 - xs.[2..] |> List.sum |> equal 7 - xs.[1..2] |> List.sum |> equal 5 - xs.[0..-1] |> List.sum |> equal 0 - xs.[-1..-1] |> List.sum |> equal 0 - xs.[-1..2] |> List.sum |> equal 6 - xs.[0..5] |> List.sum |> equal 10 + let xs = [1; 2; 3; 4] + xs.[..2] |> List.sum |> equal 6 + xs.[2..] |> List.sum |> equal 7 + xs.[1..2] |> List.sum |> equal 5 + xs.[0..-1] |> List.sum |> equal 0 + xs.[-1..-1] |> List.sum |> equal 0 + xs.[-1..2] |> List.sum |> equal 6 + xs.[0..5] |> List.sum |> equal 10 testCase "List.truncate works" <| fun () -> - [1..3] = (List.truncate 3 [1..5]) |> equal true - [1..5] = (List.truncate 10 [1..5]) |> equal true - [] = (List.truncate 0 [1..5]) |> equal true - ["str1";"str2"] = (List.truncate 2 ["str1";"str2";"str3"]) |> equal true - [] = (List.truncate 0 []) |> equal true - [] = (List.truncate 1 []) |> equal true + [1..3] = (List.truncate 3 [1..5]) |> equal true + [1..5] = (List.truncate 10 [1..5]) |> equal true + [] = (List.truncate 0 [1..5]) |> equal true + ["str1";"str2"] = (List.truncate 2 ["str1";"str2";"str3"]) |> equal true + [] = (List.truncate 0 []) |> equal true + [] = (List.truncate 1 []) |> equal true testCase "List.choose works with generic arguments" <| fun () -> let res = testListChoose [ Some [ "a" ] ] equal ["a"] res testCase "List.collect works" <| fun () -> - let xs = [[1]; [2]; [3]; [4]] - let ys = xs |> List.collect id - ys.Head + ys.Tail.Head - |> equal 3 + let xs = [[1]; [2]; [3]; [4]] + let ys = xs |> List.collect id + ys.Head + ys.Tail.Head + |> equal 3 - let list1 = [10.; 20.; 30.] - let collectList = List.collect (fun x -> [for i in 1.0..3.0 -> x * i]) list1 - sumFirstList collectList 9 |> equal 360. + let list1 = [10.; 20.; 30.] + let collectList = List.collect (fun x -> [for i in 1.0..3.0 -> x * i]) list1 + sumFirstList collectList 9 |> equal 360. - let xs = [[1.; 2.]; [3.]; [4.; 5.; 6.;]; [7.]] - let ys = xs |> List.collect id - sumFirstList ys 5 - |> equal 15. + let xs = [[1.; 2.]; [3.]; [4.; 5.; 6.;]; [7.]] + let ys = xs |> List.collect id + sumFirstList ys 5 + |> equal 15. testCase "List.concat works" <| fun () -> - let xs = [[1]; [2]; [3]; [4]] - let ys = xs |> List.concat - ys.Head + ys.Tail.Head - |> equal 3 + let xs = [[1]; [2]; [3]; [4]] + let ys = xs |> List.concat + ys.Head + ys.Tail.Head + |> equal 3 - let xs1 = [[1.; 2.; 3.]; [4.; 5.; 6.]; [7.; 8.; 9.]] - let ys1 = xs1 |> List.concat - sumFirstList ys1 7 - |> equal 28. + let xs1 = [[1.; 2.; 3.]; [4.; 5.; 6.]; [7.; 8.; 9.]] + let ys1 = xs1 |> List.concat + sumFirstList ys1 7 + |> equal 28. testCase "List.contains works" <| fun () -> - let xs = [1; 2; 3; 4] - xs |> List.contains 2 |> equal true - xs |> List.contains 0 |> equal false + let xs = [1; 2; 3; 4] + xs |> List.contains 2 |> equal true + xs |> List.contains 0 |> equal false testCase "List.contains lambda doesn't clash" <| fun () -> - let modifyList current x = - let contains = current |> List.contains x - match contains with - | true -> current |> (List.filter (fun a -> a <> x)) - | false -> x::current - let l = [1;2;3;4] - (modifyList l 1) |> List.contains 1 |> equal false - (modifyList l 5) |> List.contains 5 |> equal true + let modifyList current x = + let contains = current |> List.contains x + match contains with + | true -> current |> (List.filter (fun a -> a <> x)) + | false -> x::current + let l = [1;2;3;4] + (modifyList l 1) |> List.contains 1 |> equal false + (modifyList l 5) |> List.contains 5 |> equal true testCase "List.average works" <| fun () -> - List.average [1.; 2.; 3.; 4.] - |> equal 2.5 + List.average [1.; 2.; 3.; 4.] + |> equal 2.5 testCase "List.averageBy works" <| fun () -> - [1.; 2.; 3.; 4.] - |> List.averageBy (fun x -> x * 2.) - |> equal 5. + [1.; 2.; 3.; 4.] + |> List.averageBy (fun x -> x * 2.) + |> equal 5. testCase "List.average works with custom types" <| fun () -> [MyNumber 1; MyNumber 2; MyNumber 3] |> List.average |> equal (MyNumber 2) @@ -659,9 +659,9 @@ let tests() = xs |> List.tryFindIndexBack ((=) 5.) |> equal None testCase "List.foldBack2 works" <| fun () -> - ([1; 2; 3; 4], [1; 2; 3; 4], 0) - |||> List.foldBack2 (fun x y acc -> acc - y * x) - |> equal -30 + ([1; 2; 3; 4], [1; 2; 3; 4], 0) + |||> List.foldBack2 (fun x y acc -> acc - y * x) + |> equal -30 testCase "List.indexed works" <| fun () -> let xs = ["a"; "b"; "c"] |> List.indexed @@ -670,18 +670,18 @@ let tests() = snd xs.[2] |> equal "c" testCase "List.map3 works" <| fun () -> - let xs = [1;2;3] - let ys = [5;4;3] - let zs = [7;8;9] - let ks = List.map3 (fun x y z -> z - y - x) xs ys zs - List.sum ks - |> equal 6 + let xs = [1;2;3] + let ys = [5;4;3] + let zs = [7;8;9] + let ks = List.map3 (fun x y z -> z - y - x) xs ys zs + List.sum ks + |> equal 6 testCase "List.mapi2 works" <| fun () -> - let xs = [7;8;9] - let ys = [5;4;3] - let zs = List.mapi2 (fun i x y -> i * (x - y)) xs ys - List.sum zs |> equal 16 + let xs = [7;8;9] + let ys = [5;4;3] + let zs = List.mapi2 (fun i x y -> i * (x - y)) xs ys + List.sum zs |> equal 16 testCase "List.mapFold works" <| fun () -> let xs = [1y; 2y; 3y; 4y] @@ -706,11 +706,11 @@ let tests() = equal "a" xs.Head testCase "List.partition works" <| fun () -> - let xs = [1; 2; 3; 4; 5; 6] - let ys, zs = xs |> List.partition (fun x -> x % 2 = 0) - List.sum zs |> equal 9 - equal 2 ys.[0] - equal 5 zs.[2] + let xs = [1; 2; 3; 4; 5; 6] + let ys, zs = xs |> List.partition (fun x -> x % 2 = 0) + List.sum zs |> equal 9 + equal 2 ys.[0] + equal 5 zs.[2] testCase "List.pairwise works" <| fun () -> List.pairwise [] |> equal [] @@ -723,10 +723,10 @@ let tests() = |> equal "122334" testCase "List.permute works" <| fun () -> - let xs = [1; 2; 3; 4; 5; 6] - let ys = xs |> List.permute (fun i -> i + 1 - 2 * (i % 2)) - equal 4 ys.[2] - equal 6 ys.[4] + let xs = [1; 2; 3; 4; 5; 6] + let ys = xs |> List.permute (fun i -> i + 1 - 2 * (i % 2)) + equal 4 ys.[2] + equal 6 ys.[4] testCase "List.chunkBySize works" <| fun () -> [1..8] |> List.chunkBySize 4 |> equal [ [1..4]; [5..8] ] @@ -741,14 +741,14 @@ let tests() = |> equal 20 testCase "List.zip3 works" <| fun () -> - let xs = [1; 2; 3] - let ys = [4; 5; 6] - let zs = [7; 8; 9] - let ks = List.zip3 xs ys zs - let x, y, z = List.last ks - equal 3 x - equal 6 y - equal 9 z + let xs = [1; 2; 3] + let ys = [4; 5; 6] + let zs = [7; 8; 9] + let ks = List.zip3 xs ys zs + let x, y, z = List.last ks + equal 3 x + equal 6 y + equal 9 z testCase "List.tryItem works" <| fun () -> let xs = [1.; 2.; 3.; 4.] @@ -867,11 +867,11 @@ let tests() = makeList false |> List.sum |> equal 3 testCase "List.splitInto works" <| fun () -> - [1..10] |> List.splitInto 3 |> equal [ [1..4]; [5..7]; [8..10] ] - [1..11] |> List.splitInto 3 |> equal [ [1..4]; [5..8]; [9..11] ] - [1..12] |> List.splitInto 3 |> equal [ [1..4]; [5..8]; [9..12] ] - [1..5] |> List.splitInto 4 |> equal [ [1..2]; [3]; [4]; [5] ] - [1..4] |> List.splitInto 20 |> equal [ [1]; [2]; [3]; [4] ] + [1..10] |> List.splitInto 3 |> equal [ [1..4]; [5..7]; [8..10] ] + [1..11] |> List.splitInto 3 |> equal [ [1..4]; [5..8]; [9..11] ] + [1..12] |> List.splitInto 3 |> equal [ [1..4]; [5..8]; [9..12] ] + [1..5] |> List.splitInto 4 |> equal [ [1..2]; [3]; [4]; [5] ] + [1..4] |> List.splitInto 20 |> equal [ [1]; [2]; [3]; [4] ] testCase "List.transpose works" <| fun () -> // integer list diff --git a/tests/Js/Main/ArrayTests.fs b/tests/Js/Main/ArrayTests.fs index 079e6c25c..dad94e33c 100644 --- a/tests/Js/Main/ArrayTests.fs +++ b/tests/Js/Main/ArrayTests.fs @@ -1,11 +1,11 @@ module Fable.Tests.Arrays -open System +open System.Collections.Generic open Util.Testing open Fable.Tests.Util type ParamArrayTest = - static member Add([] xs: int[]) = Array.sum xs + static member Add([] xs: int[]) = Array.sum xs let add (xs: int[]) = ParamArrayTest.Add(xs) @@ -423,7 +423,7 @@ let tests = testCase "Array.filter with chars works" <| fun () -> let xs = [|'a'; '2'; 'b'; 'c'|] - let ys = xs |> Array.filter Char.IsLetter + let ys = xs |> Array.filter System.Char.IsLetter ys.Length |> equal 3 testCase "Array.find works" <| fun () -> @@ -1066,16 +1066,16 @@ let tests = ys :? System.Array |> equal true zs :? System.Array |> equal false - testCase "Array.Copy works with numeric arrays" <| fun () -> + testCase "System.Array.Copy works with numeric arrays" <| fun () -> let source = [| 99 |] let destination = [| 1; 2; 3 |] - Array.Copy(source, 0, destination, 0, 1) + System.Array.Copy(source, 0, destination, 0, 1) equal [| 99; 2; 3 |] destination - testCase "Array.Copy works with non-numeric arrays" <| fun () -> + testCase "System.Array.Copy works with non-numeric arrays" <| fun () -> let source = [| "xy"; "xx"; "xyz" |] let destination = [| "a"; "b"; "c" |] - Array.Copy(source, 1, destination, 1, 2) + System.Array.Copy(source, 1, destination, 1, 2) equal [| "a"; "xx"; "xyz" |] destination testCase "Array.splitInto works" <| fun () -> @@ -1221,18 +1221,42 @@ let tests = equal c2 -1 equal c3 1 - testCase "Array.Resize works" <| fun () -> + testCase "System.Array.Resize works" <| fun () -> let mutable xs = [|1; 2; 3; 4; 5|] - Array.Resize(&xs, 3) + System.Array.Resize(&xs, 3) xs |> equal [|1; 2; 3|] - Array.Resize(&xs, 7) + System.Array.Resize(&xs, 7) xs |> equal [|1; 2; 3; 0; 0; 0; 0|] - Array.Resize(&xs, 0) + System.Array.Resize(&xs, 0) xs |> equal [||] xs <- null - Array.Resize(&xs, 3) + System.Array.Resize(&xs, 3) xs |> equal [|0; 0; 0|] xs <- null - Array.Resize(&xs, 0) + System.Array.Resize(&xs, 0) xs |> equal [||] + + // testCase "Array ICollection.IsReadOnly works" <| fun _ -> + // let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + // let coll = xs :> ICollection<_> + // coll.IsReadOnly |> equal false + + testCase "Array ICollection.Count works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = xs :> ICollection<_> + coll.Count |> equal 3 + + testCase "Array ICollection.Contains works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = xs :> ICollection<_> + coll.Contains(("B", 3)) |> equal false + coll.Contains(("D", 3)) |> equal false + coll.Contains(("B", 2)) |> equal true + + testCase "Array ICollection.CopyTo works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = xs :> ICollection<_> + let ys = [| ("D", 4); ("E", 5); ("F", 6) |] + coll.CopyTo(ys, 0) + ys = xs |> equal true ] diff --git a/tests/Js/Main/DictionaryTests.fs b/tests/Js/Main/DictionaryTests.fs index 29d7fb1f5..d52eb5600 100644 --- a/tests/Js/Main/DictionaryTests.fs +++ b/tests/Js/Main/DictionaryTests.fs @@ -235,7 +235,8 @@ let tests = testCase "Adding 2 items with the same key throws" <| fun () -> let dic = Dictionary<_,_>() dic.Add("A", 65) - throwsError "An item with the same key has already been added. Key: A" (fun _ -> dic.Add("A", 95)) + // throwsError "An item with the same key has already been added. Key: A" (fun _ -> dic.Add("A", 95)) + throwsAnyError (fun _ -> dic.Add("A", 95)) testCase "Indexer throws when key not found" <| fun () -> let dic = Dictionary<_,_>() @@ -244,12 +245,12 @@ let tests = throwsAnyError (fun () -> dic.["B"]) testCase "conversion from array works" <| fun () -> - let dic = [| "A",1; "B",2|] |> dict + let dic = [| "A",1; "B",2 |] |> dict dic.Values.Count |> equal 2 testCase "conversion from array works with duplicates" <| fun () -> - let dic = [| "A",1; "A",3; "B",2|] |> dict + let dic = [| "A",1; "A",3; "B",2 |] |> dict dic.Values.Count |> equal 2 @@ -269,4 +270,50 @@ let tests = table.add "B" 2 table.add "C" 3 table.Dic.Count |> equal 3 + + testCase "Dictionary ICollection.IsReadOnly works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] |> Array.map KeyValuePair + let coll = (Dictionary xs) :> ICollection> + coll.IsReadOnly |> equal false + + testCase "Dictionary ICollection.Count works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] |> Array.map KeyValuePair + let coll = (Dictionary xs) :> ICollection> + coll.Count |> equal 3 + + testCase "Dictionary ICollection.Contains works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] |> Array.map KeyValuePair + let coll = (Dictionary xs) :> ICollection> + coll.Contains(KeyValuePair("B", 3)) |> equal false + coll.Contains(KeyValuePair("D", 3)) |> equal false + coll.Contains(KeyValuePair("B", 2)) |> equal true + + testCase "Dictionary ICollection.CopyTo works" <| fun _ -> // See #3914 + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] |> Array.map KeyValuePair + let coll = (Dictionary xs) :> ICollection> + let ys = [| ("D", 4); ("E", 5); ("F", 6) |] |> Array.map KeyValuePair + coll.CopyTo(ys, 0) + ys = xs |> equal true + + testCase "Dictionary ICollection.Clear works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] |> Array.map KeyValuePair + let coll = (Dictionary xs) :> ICollection> + coll.Clear() + coll.Count |> equal 0 + + testCase "Dictionary ICollection.Add works" <| fun _ -> // See #3914 + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] |> Array.map KeyValuePair + let coll = (Dictionary xs) :> ICollection> + throwsAnyError (fun _ -> coll.Add(KeyValuePair("A", 1))) + throwsAnyError (fun _ -> coll.Add(KeyValuePair("A", 2))) + coll.Add(KeyValuePair("D", 4)) + coll.Count |> equal 4 + + testCase "Dictionary ICollection.Remove works" <| fun _ -> // See #3914 + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] |> Array.map KeyValuePair + let coll = (Dictionary xs) :> ICollection> + coll.Remove(KeyValuePair("B", 3)) |> equal false + coll.Remove(KeyValuePair("D", 3)) |> equal false + coll.Remove(KeyValuePair("B", 2)) |> equal true + coll.Count |> equal 2 ] diff --git a/tests/Js/Main/HashSetTests.fs b/tests/Js/Main/HashSetTests.fs index 3a02a85ad..5c7393061 100644 --- a/tests/Js/Main/HashSetTests.fs +++ b/tests/Js/Main/HashSetTests.fs @@ -1,7 +1,7 @@ module Fable.Tests.HashSets -open Util.Testing open System.Collections.Generic +open Util.Testing type MyRefType(i: int) = member x.Value = i @@ -222,4 +222,49 @@ let tests = apa.Contains ({ i = 5; s = "foo"}) |> equal true apa.Contains ({ i = 5; s = "fo"}) |> equal false + testCase "HashSet ICollection.IsReadOnly works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (HashSet xs) :> ICollection<_> + coll.IsReadOnly |> equal false + + testCase "HashSet ICollection.Count works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (HashSet xs) :> ICollection<_> + coll.Count |> equal 3 + + testCase "HashSet ICollection.Contains works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (HashSet xs) :> ICollection<_> + coll.Contains(("B", 3)) |> equal false + coll.Contains(("D", 3)) |> equal false + coll.Contains(("B", 2)) |> equal true + + testCase "HashSet ICollection.CopyTo works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (HashSet xs) :> ICollection<_> + let ys = [| ("D", 4); ("E", 5); ("F", 6) |] + coll.CopyTo(ys, 0) + ys = xs |> equal true + + testCase "HashSet ICollection.Clear works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (HashSet xs) :> ICollection<_> + coll.Clear() + coll.Count |> equal 0 + + testCase "HashSet ICollection.Add works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (HashSet xs) :> ICollection<_> + coll.Add(("A", 1)) + coll.Add(("A", 2)) + coll.Add(("D", 4)) + coll.Count |> equal 5 + + testCase "HashSet ICollection.Remove works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (HashSet xs) :> ICollection<_> + coll.Remove(("B", 3)) |> equal false + coll.Remove(("D", 3)) |> equal false + coll.Remove(("B", 2)) |> equal true + coll.Count |> equal 2 ] \ No newline at end of file diff --git a/tests/Js/Main/ListTests.fs b/tests/Js/Main/ListTests.fs index 13ec81d13..e742c3880 100644 --- a/tests/Js/Main/ListTests.fs +++ b/tests/Js/Main/ListTests.fs @@ -75,292 +75,292 @@ let tests = |> equal 1 testCase "List.Length works" <| fun () -> - let xs = [1; 2; 3; 4] - equal 4 xs.Length - equal 0 [].Length + let xs = [1; 2; 3; 4] + equal 4 xs.Length + equal 0 [].Length testCase "List.IsEmpty works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [] - equal false xs.IsEmpty - equal false [1; 2; 3; 4].IsEmpty - equal true ys.IsEmpty - equal true [].IsEmpty + let xs = [1; 2; 3; 4] + let ys = [] + equal false xs.IsEmpty + equal false [1; 2; 3; 4].IsEmpty + equal true ys.IsEmpty + equal true [].IsEmpty testCase "List.Equals works" <| fun () -> - let xs = [1;2;3] - xs.Equals(xs) |> equal true + let xs = [1;2;3] + xs.Equals(xs) |> equal true testCase "List.Head works" <| fun () -> - let xs = [1; 2; 3; 4] - equal 1 xs.Head + let xs = [1; 2; 3; 4] + equal 1 xs.Head testCase "List.Tail works" <| fun () -> - let xs = [1; 2; 3; 4] - equal 2 xs.Tail.Head + let xs = [1; 2; 3; 4] + equal 2 xs.Tail.Head testCase "List.Item works" <| fun () -> - let xs = [1; 2; 3; 4] - equal 4 xs.[3] + let xs = [1; 2; 3; 4] + equal 4 xs.[3] testCase "List cons works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = 3 :: xs - let zs = List.Cons(4, xs) - ys.Head + xs.Head - |> equal zs.Head + let xs = [1; 2; 3; 4] + let ys = 3 :: xs + let zs = List.Cons(4, xs) + ys.Head + xs.Head + |> equal zs.Head testCase "List.cons works II" <| fun () -> - let li = [1;2;3;4;5] - let li2 = li.Tail - let li3 = [8;9;11] @ li2 - let li3b = [20;16] @ li3.Tail - let li4 = 14 :: li3b - li4.[1] |> equal 20 - li4.[3] |> equal 9 - List.length li4 |> equal 9 - List.sum li4 |> equal 84 + let li = [1;2;3;4;5] + let li2 = li.Tail + let li3 = [8;9;11] @ li2 + let li3b = [20;16] @ li3.Tail + let li4 = 14 :: li3b + li4.[1] |> equal 20 + li4.[3] |> equal 9 + List.length li4 |> equal 9 + List.sum li4 |> equal 84 testCase "List.empty works" <| fun () -> - let xs = 1 :: List.Empty - let ys = 1 :: List.empty - xs.Length + ys.Length |> equal 2 + let xs = 1 :: List.Empty + let ys = 1 :: List.empty + xs.Length + ys.Length |> equal 2 testCase "List.append works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [0] - let zs = List.append ys xs - zs.Head + zs.Tail.Head - |> equal 1 + let xs = [1; 2; 3; 4] + let ys = [0] + let zs = List.append ys xs + zs.Head + zs.Tail.Head + |> equal 1 testCase "List.append works II" <| fun () -> - let li = [1;2;3;4;5] - let li2 = li.Tail - let li3 = [8;9;11] @ li2 - let li3b = [20;16] @ li3.Tail - let li4 = li3b @ li2 - li4.[1] |> equal 16 - li4.[9] |> equal 3 - List.length li4 |> equal 12 - List.sum li4 |> equal 84 + let li = [1;2;3;4;5] + let li2 = li.Tail + let li3 = [8;9;11] @ li2 + let li3b = [20;16] @ li3.Tail + let li4 = li3b @ li2 + li4.[1] |> equal 16 + li4.[9] |> equal 3 + List.length li4 |> equal 12 + List.sum li4 |> equal 84 testCase "List.append works with empty list" <| fun () -> - let li = [{| value = 2|}; {| value = 4|};] - let li = li @ [] - let li = [] @ li - li - |> Seq.map (fun x -> 20 / x.value) - |> Seq.sum - |> equal 15 + let li = [{| value = 2|}; {| value = 4|};] + let li = li @ [] + let li = [] @ li + li + |> Seq.map (fun x -> 20 / x.value) + |> Seq.sum + |> equal 15 testCase "List.choose works" <| fun () -> - let xs = [1; 2; 3; 4] - let result = xs |> List.choose (fun x -> - if x > 2 then Some x - else None) - result.Head + result.Tail.Head - |> equal 7 + let xs = [1; 2; 3; 4] + let result = xs |> List.choose (fun x -> + if x > 2 then Some x + else None) + result.Head + result.Tail.Head + |> equal 7 testCase "List.exactlyOne works" <| fun () -> - let xs = [1.;] - xs |> List.exactlyOne - |> equal 1. + let xs = [1.;] + xs |> List.exactlyOne + |> equal 1. - let xs2 = [1.;2.] - (try List.exactlyOne xs2 |> ignore; false with | _ -> true) |> equal true + let xs2 = [1.;2.] + (try List.exactlyOne xs2 |> ignore; false with | _ -> true) |> equal true - let xs3 = [] - (try List.exactlyOne xs3 |> ignore; false with | _ -> true) |> equal true + let xs3 = [] + (try List.exactlyOne xs3 |> ignore; false with | _ -> true) |> equal true testCase "List.tryExactlyOne works" <| fun () -> - [1.] |> List.tryExactlyOne |> equal (Some 1.) - [1.;2.] |> List.tryExactlyOne |> equal None - [] |> List.tryExactlyOne |> equal None + [1.] |> List.tryExactlyOne |> equal (Some 1.) + [1.;2.] |> List.tryExactlyOne |> equal None + [] |> List.tryExactlyOne |> equal None testCase "List.exists works" <| fun () -> - let xs = [1; 2; 3; 4] - xs |> List.exists (fun x -> x = 2) - |> equal true + let xs = [1; 2; 3; 4] + xs |> List.exists (fun x -> x = 2) + |> equal true testCase "List.exists2 works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [1; 2; 3; 4] - List.exists2 (fun x y -> x * y = 16) xs ys - |> equal true + let xs = [1; 2; 3; 4] + let ys = [1; 2; 3; 4] + List.exists2 (fun x y -> x * y = 16) xs ys + |> equal true testCase "List.filter works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = xs |> List.filter (fun x -> x > 5) - equal ys.IsEmpty true + let xs = [1; 2; 3; 4] + let ys = xs |> List.filter (fun x -> x > 5) + equal ys.IsEmpty true testCase "List.filter doesn't work backwards" <| fun () -> // See #1672 - let li = [1; 2; 3; 4; 5] - li |> List.filteri (fun i _ -> i <> 1) |> equal [1; 3; 4; 5] + let li = [1; 2; 3; 4; 5] + li |> List.filteri (fun i _ -> i <> 1) |> equal [1; 3; 4; 5] testCase "List.find works" <| fun () -> - [1; 2; 3; 4] - |> List.find ((=) 2) - |> equal 2 + [1; 2; 3; 4] + |> List.find ((=) 2) + |> equal 2 testCase "List.findIndex works" <| fun () -> - [1; 2; 3; 4] - |> List.findIndex ((=) 2) - |> equal 1 + [1; 2; 3; 4] + |> List.findIndex ((=) 2) + |> equal 1 testCase "List.fold works" <| fun () -> - [1; 2; 3; 4] - |> List.fold (+) 0 - |> equal 10 + [1; 2; 3; 4] + |> List.fold (+) 0 + |> equal 10 testCase "List.fold2 works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [1; 2; 3; 4] - List.fold2 (fun x y z -> x + y + z) 0 xs ys - |> equal 20 + let xs = [1; 2; 3; 4] + let ys = [1; 2; 3; 4] + List.fold2 (fun x y z -> x + y + z) 0 xs ys + |> equal 20 testCase "List.foldBack works" <| fun () -> - [1; 2; 3; 4] - |> List.foldBack (fun x acc -> acc - x) <| 100 - |> equal 90 + [1; 2; 3; 4] + |> List.foldBack (fun x acc -> acc - x) <| 100 + |> equal 90 testCase "List.foldBack with composition works" <| fun () -> - [1; 2; 3; 4] - |> List.foldBack (fun x acc -> acc >> (+) x) <| id <| 2 - |> equal 12 + [1; 2; 3; 4] + |> List.foldBack (fun x acc -> acc >> (+) x) <| id <| 2 + |> equal 12 testCase "List.forall works" <| fun () -> - [1; 2; 3; 4] - |> List.forall (fun x -> x < 5) - |> equal true + [1; 2; 3; 4] + |> List.forall (fun x -> x < 5) + |> equal true testCase "List.forall2 works" <| fun () -> - ([1; 2; 3; 4], [1; 2; 3; 4]) - ||> List.forall2 (=) - |> equal true + ([1; 2; 3; 4], [1; 2; 3; 4]) + ||> List.forall2 (=) + |> equal true testCase "List.head works" <| fun () -> - [1; 2; 3; 4] - |> List.head - |> equal 1 + [1; 2; 3; 4] + |> List.head + |> equal 1 testCase "List.init works" <| fun () -> - let xs = List.init 4 float - xs.Head + xs.Tail.Head - |> equal 1. + let xs = List.init 4 float + xs.Head + xs.Tail.Head + |> equal 1. testCase "List.isEmpty works" <| fun () -> - List.isEmpty [1] |> equal false - List.isEmpty [] |> equal true + List.isEmpty [1] |> equal false + List.isEmpty [] |> equal true testCase "List.iter works" <| fun () -> - let xs = [1; 2; 3; 4] - let mutable total = 0 - xs |> List.iter (fun x -> - total <- total + x) - equal 10 total + let xs = [1; 2; 3; 4] + let mutable total = 0 + xs |> List.iter (fun x -> + total <- total + x) + equal 10 total testCase "List.iter2 works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [2; 4; 6; 8] - let total = ref 0 - List.iter2 (fun x y -> - total := !total + (y - x) - ) xs ys - equal 10 !total + let xs = [1; 2; 3; 4] + let ys = [2; 4; 6; 8] + let total = ref 0 + List.iter2 (fun x y -> + total := !total + (y - x) + ) xs ys + equal 10 !total testCase "List.iteri works" <| fun () -> - let mutable total = 0 - [1; 2; 3; 4] - |> List.iteri (fun i x -> - total <- total + (i * x)) - equal 20 total + let mutable total = 0 + [1; 2; 3; 4] + |> List.iteri (fun i x -> + total <- total + (i * x)) + equal 20 total testCase "List.iteri2 works" <| fun () -> - let mutable total = 0 - let xs = [1; 2; 3; 4] - let ys = [2; 4; 6; 8] - List.iteri2 (fun i x y -> + let mutable total = 0 + let xs = [1; 2; 3; 4] + let ys = [2; 4; 6; 8] + List.iteri2 (fun i x y -> total <- total + i * (y - x) ) xs ys - equal 20 total + equal 20 total testCase "List.length works" <| fun () -> - let xs = [1; 2; 3; 4] - List.length xs - |> equal 4 + let xs = [1; 2; 3; 4] + List.length xs + |> equal 4 testCase "List.item works" <| fun () -> - [1; 2] |> List.item 1 |> equal 2 + [1; 2] |> List.item 1 |> equal 2 testCase "List.map works" <| fun () -> - let xs = [1;2;3] - let ys = xs |> List.map ((*) 2) - equal 4 ys.Tail.Head + let xs = [1;2;3] + let ys = xs |> List.map ((*) 2) + equal 4 ys.Tail.Head testCase "List.mapi works" <| fun () -> - let xs = [1] - let ys = xs |> List.mapi (fun i x -> i * x) - equal 0 ys.Head + let xs = [1] + let ys = xs |> List.mapi (fun i x -> i * x) + equal 0 ys.Head testCase "List.map2 works" <| fun () -> - let xs = [1;2] - let ys = [2;3] - let zs = List.map2 (fun x y -> x - y) xs ys - equal -1 zs.Head + let xs = [1;2] + let ys = [2;3] + let zs = List.map2 (fun x y -> x - y) xs ys + equal -1 zs.Head testCase "List.ofArray works" <| fun () -> - let xs = [|1; 2|] - let ys = List.ofArray xs - ys.Head |> equal 1 + let xs = [|1; 2|] + let ys = List.ofArray xs + ys.Head |> equal 1 - let xs1 = [|1.; 2.; 3.; 4.|] - let ys1 = List.ofArray xs1 - sumFirstList ys1 3 |> equal 6. + let xs1 = [|1.; 2.; 3.; 4.|] + let ys1 = List.ofArray xs1 + sumFirstList ys1 3 |> equal 6. testCase "List.ofSeq works" <| fun () -> - // let xs = [|1; 2|] :> _ seq - let ys = List.ofSeq <| seq { yield 1; yield 2 } - ys.Head |> equal 1 - ys.Length |> equal 2 + // let xs = [|1; 2|] :> _ seq + let ys = List.ofSeq <| seq { yield 1; yield 2 } + ys.Head |> equal 1 + ys.Length |> equal 2 testCase "List.pick works" <| fun () -> - let xs = [1; 2] - xs |> List.pick (fun x -> - match x with - | 2 -> Some x - | _ -> None) - |> equal 2 + let xs = [1; 2] + xs |> List.pick (fun x -> + match x with + | 2 -> Some x + | _ -> None) + |> equal 2 testCase "List.reduce works" <| fun () -> - let xs = [1; 2] - xs |> List.reduce (+) - |> equal 3 + let xs = [1; 2] + xs |> List.reduce (+) + |> equal 3 testCase "List.reduceBack works" <| fun () -> - let xs = [1; 2] - xs |> List.reduceBack (+) - |> equal 3 + let xs = [1; 2] + xs |> List.reduceBack (+) + |> equal 3 testCase "List.replicate works" <| fun () -> - List.replicate 3 3 - |> List.sum |> equal 9 + List.replicate 3 3 + |> List.sum |> equal 9 testCase "List.rev works" <| fun () -> - let xs = [1; 2; 3] - let ys = xs |> List.rev - equal 3 ys.Head + let xs = [1; 2; 3] + let ys = xs |> List.rev + equal 3 ys.Head testCase "List.scan works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = (0, xs) ||> List.scan (fun acc x -> acc - x) - ys.[3] + ys.[4] - |> equal -16 + let xs = [1; 2; 3; 4] + let ys = (0, xs) ||> List.scan (fun acc x -> acc - x) + ys.[3] + ys.[4] + |> equal -16 testCase "List.scanBack works" <| fun () -> - let xs = [1; 2; 3] - let ys = List.scanBack (fun x acc -> acc - x) xs 0 - ys.Head + ys.Tail.Head - |> equal -11 + let xs = [1; 2; 3] + let ys = List.scanBack (fun x acc -> acc - x) xs 0 + ys.Head + ys.Tail.Head + |> equal -11 testCase "List.sort works" <| fun () -> let xs = [3; 4; 1; -3; 2; 10] @@ -398,47 +398,47 @@ let tests = |> equal 3 testCase "List.max works" <| fun () -> - let xs = [1; 2] - xs |> List.max - |> equal 2 + let xs = [1; 2] + xs |> List.max + |> equal 2 testCase "List.maxBy works" <| fun () -> - let xs = [1; 2] - xs |> List.maxBy (fun x -> -x) - |> equal 1 + let xs = [1; 2] + xs |> List.maxBy (fun x -> -x) + |> equal 1 testCase "List.min works" <| fun () -> - let xs = [1; 2] - xs |> List.min - |> equal 1 + let xs = [1; 2] + xs |> List.min + |> equal 1 testCase "List.minBy works" <| fun () -> - let xs = [1; 2] - xs |> List.minBy (fun x -> -x) - |> equal 2 + let xs = [1; 2] + xs |> List.minBy (fun x -> -x) + |> equal 2 testCase "List.sum works" <| fun () -> - [1; 2] |> List.sum - |> equal 3 + [1; 2] |> List.sum + |> equal 3 testCase "List.sumBy works" <| fun () -> - [1; 2] |> List.sumBy (fun x -> x*2) - |> equal 6 + [1; 2] |> List.sumBy (fun x -> x*2) + |> equal 6 testCase "List.sum with non numeric types works" <| fun () -> - let p1 = {x=1; y=10} - let p2 = {x=2; y=20} - [p1; p2] |> List.sum |> (=) {x=3;y=30} |> equal true + let p1 = {x=1; y=10} + let p2 = {x=2; y=20} + [p1; p2] |> List.sum |> (=) {x=3;y=30} |> equal true testCase "List.sumBy with non numeric types works" <| fun () -> - let p1 = {x=1; y=10} - let p2 = {x=2; y=20} - [p1; p2] |> List.sumBy Point.Neg |> (=) {x = -3; y = -30} |> equal true + let p1 = {x=1; y=10} + let p2 = {x=2; y=20} + [p1; p2] |> List.sumBy Point.Neg |> (=) {x = -3; y = -30} |> equal true testCase "List.sumBy with numeric projection works" <| fun () -> - let p1 = {x=1; y=10} - let p2 = {x=2; y=20} - [p1; p2] |> List.sumBy (fun p -> p.y) |> equal 30 + let p1 = {x=1; y=10} + let p2 = {x=2; y=20} + [p1; p2] |> List.sumBy (fun p -> p.y) |> equal 30 testCase "List.sum with non numeric types works II" <| fun () -> [MyNumber 1; MyNumber 2; MyNumber 3] |> List.sum |> equal (MyNumber 6) @@ -475,142 +475,142 @@ let tests = |> equal 2. testCase "List.tail works" <| fun () -> - let xs = [1; 2] - let ys = xs |> List.tail - equal 1 ys.Length + let xs = [1; 2] + let ys = xs |> List.tail + equal 1 ys.Length testCase "List.toArray works" <| fun () -> - let ys = List.toArray [1; 2] - ys.[0] + ys.[1] |> equal 3 - let xs = [1; 1] - let ys2 = List.toArray (2::xs) - ys2.[0] + ys2.[1] + ys2.[2] |> equal 4 + let ys = List.toArray [1; 2] + ys.[0] + ys.[1] |> equal 3 + let xs = [1; 1] + let ys2 = List.toArray (2::xs) + ys2.[0] + ys2.[1] + ys2.[2] |> equal 4 testCase "List.toSeq works" <| fun () -> - [1; 2] - |> List.toSeq - |> Seq.tail |> Seq.head - |> equal 2 + [1; 2] + |> List.toSeq + |> Seq.tail |> Seq.head + |> equal 2 testCase "List.tryPick works" <| fun () -> - [1; 2] - |> List.tryPick (function - | 2 -> Some 2 - | _ -> None) - |> function - | Some x -> x - | None -> 0 - |> equal 2 + [1; 2] + |> List.tryPick (function + | 2 -> Some 2 + | _ -> None) + |> function + | Some x -> x + | None -> 0 + |> equal 2 testCase "List.tryFind works" <| fun () -> - [1; 2] - |> List.tryFind ((=) 5) - |> equal None + [1; 2] + |> List.tryFind ((=) 5) + |> equal None testCase "List.tryFindIndex works" <| fun () -> - let xs = [1; 2] - let ys = xs |> List.tryFindIndex ((=) 2) - ys.Value |> equal 1 - xs |> List.tryFindIndex ((=) 5) |> equal None + let xs = [1; 2] + let ys = xs |> List.tryFindIndex ((=) 2) + ys.Value |> equal 1 + xs |> List.tryFindIndex ((=) 5) |> equal None testCase "List.unzip works" <| fun () -> - let xs = [1, 2] - let ys, zs = xs |> List.unzip - ys.Head + zs.Head - |> equal 3 + let xs = [1, 2] + let ys, zs = xs |> List.unzip + ys.Head + zs.Head + |> equal 3 testCase "List.unzip3 works" <| fun () -> - let xs = [(1, 2, 3); (4, 5, 6)] - let ys, zs, ks = xs |> List.unzip3 - ys.[1] + zs.[1] + ks.[1] - |> equal 15 + let xs = [(1, 2, 3); (4, 5, 6)] + let ys, zs, ks = xs |> List.unzip3 + ys.[1] + zs.[1] + ks.[1] + |> equal 15 testCase "List.zip works" <| fun () -> - let xs = [1; 2; 3] - let ys = [4; 5; 6] - let zs = List.zip xs ys - let x, y = zs.Tail.Head - equal 2 x - equal 5 y + let xs = [1; 2; 3] + let ys = [4; 5; 6] + let zs = List.zip xs ys + let x, y = zs.Tail.Head + equal 2 x + equal 5 y testCase "List snail to append works" <| fun () -> - let xs = [1; 2; 3; 4] - let ys = [0] - let zs = ys @ xs - zs.Head + zs.Tail.Head - |> equal 1 + let xs = [1; 2; 3; 4] + let ys = [0] + let zs = ys @ xs + zs.Head + zs.Tail.Head + |> equal 1 testCase "List slice works" <| fun () -> - let xs = [1; 2; 3; 4] - xs.[..2] |> List.sum |> equal 6 - xs.[2..] |> List.sum |> equal 7 - xs.[1..2] |> List.sum |> equal 5 - xs.[0..-1] |> List.sum |> equal 0 - xs.[-1..-1] |> List.sum |> equal 0 - xs.[-1..2] |> List.sum |> equal 6 - xs.[0..5] |> List.sum |> equal 10 + let xs = [1; 2; 3; 4] + xs.[..2] |> List.sum |> equal 6 + xs.[2..] |> List.sum |> equal 7 + xs.[1..2] |> List.sum |> equal 5 + xs.[0..-1] |> List.sum |> equal 0 + xs.[-1..-1] |> List.sum |> equal 0 + xs.[-1..2] |> List.sum |> equal 6 + xs.[0..5] |> List.sum |> equal 10 testCase "List.truncate works" <| fun () -> - [1..3] = (List.truncate 3 [1..5]) |> equal true - [1..5] = (List.truncate 10 [1..5]) |> equal true - [] = (List.truncate 0 [1..5]) |> equal true - ["str1";"str2"] = (List.truncate 2 ["str1";"str2";"str3"]) |> equal true - [] = (List.truncate 0 []) |> equal true - [] = (List.truncate 1 []) |> equal true + [1..3] = (List.truncate 3 [1..5]) |> equal true + [1..5] = (List.truncate 10 [1..5]) |> equal true + [] = (List.truncate 0 [1..5]) |> equal true + ["str1";"str2"] = (List.truncate 2 ["str1";"str2";"str3"]) |> equal true + [] = (List.truncate 0 []) |> equal true + [] = (List.truncate 1 []) |> equal true testCase "List.choose works with generic arguments" <| fun () -> let res = testListChoose [ Some [ "a" ] ] equal ["a"] res testCase "List.collect works" <| fun () -> - let xs = [[1]; [2]; [3]; [4]] - let ys = xs |> List.collect id - ys.Head + ys.Tail.Head - |> equal 3 + let xs = [[1]; [2]; [3]; [4]] + let ys = xs |> List.collect id + ys.Head + ys.Tail.Head + |> equal 3 - let list1 = [10.; 20.; 30.] - let collectList = List.collect (fun x -> [for i in 1.0..3.0 -> x * i]) list1 - sumFirstList collectList 9 |> equal 360. + let list1 = [10.; 20.; 30.] + let collectList = List.collect (fun x -> [for i in 1.0..3.0 -> x * i]) list1 + sumFirstList collectList 9 |> equal 360. - let xs = [[1.; 2.]; [3.]; [4.; 5.; 6.;]; [7.]] - let ys = xs |> List.collect id - sumFirstList ys 5 - |> equal 15. + let xs = [[1.; 2.]; [3.]; [4.; 5.; 6.;]; [7.]] + let ys = xs |> List.collect id + sumFirstList ys 5 + |> equal 15. testCase "List.concat works" <| fun () -> - let xs = [[1]; [2]; [3]; [4]] - let ys = xs |> List.concat - ys.Head + ys.Tail.Head - |> equal 3 + let xs = [[1]; [2]; [3]; [4]] + let ys = xs |> List.concat + ys.Head + ys.Tail.Head + |> equal 3 - let xs1 = [[1.; 2.; 3.]; [4.; 5.; 6.]; [7.; 8.; 9.]] - let ys1 = xs1 |> List.concat - sumFirstList ys1 7 - |> equal 28. + let xs1 = [[1.; 2.; 3.]; [4.; 5.; 6.]; [7.; 8.; 9.]] + let ys1 = xs1 |> List.concat + sumFirstList ys1 7 + |> equal 28. testCase "List.contains works" <| fun () -> - let xs = [1; 2; 3; 4] - xs |> List.contains 2 |> equal true - xs |> List.contains 0 |> equal false + let xs = [1; 2; 3; 4] + xs |> List.contains 2 |> equal true + xs |> List.contains 0 |> equal false testCase "List.contains lambda doesn't clash" <| fun () -> - let modifyList current x = - let contains = current |> List.contains x - match contains with - | true -> current |> (List.filter (fun a -> a <> x)) - | false -> x::current - let l = [1;2;3;4] - (modifyList l 1) |> List.contains 1 |> equal false - (modifyList l 5) |> List.contains 5 |> equal true + let modifyList current x = + let contains = current |> List.contains x + match contains with + | true -> current |> (List.filter (fun a -> a <> x)) + | false -> x::current + let l = [1;2;3;4] + (modifyList l 1) |> List.contains 1 |> equal false + (modifyList l 5) |> List.contains 5 |> equal true testCase "List.average works" <| fun () -> - List.average [1.; 2.; 3.; 4.] - |> equal 2.5 + List.average [1.; 2.; 3.; 4.] + |> equal 2.5 testCase "List.averageBy works" <| fun () -> - [1.; 2.; 3.; 4.] - |> List.averageBy (fun x -> x * 2.) - |> equal 5. + [1.; 2.; 3.; 4.] + |> List.averageBy (fun x -> x * 2.) + |> equal 5. testCase "List.average works with custom types" <| fun () -> [MyNumber 1; MyNumber 2; MyNumber 3] |> List.average |> equal (MyNumber 2) @@ -666,9 +666,9 @@ let tests = xs |> List.tryFindIndexBack ((=) 5.) |> equal None testCase "List.foldBack2 works" <| fun () -> - ([1; 2; 3; 4], [1; 2; 3; 4], 0) - |||> List.foldBack2 (fun x y acc -> acc - y * x) - |> equal -30 + ([1; 2; 3; 4], [1; 2; 3; 4], 0) + |||> List.foldBack2 (fun x y acc -> acc - y * x) + |> equal -30 testCase "List.indexed works" <| fun () -> let xs = ["a"; "b"; "c"] |> List.indexed @@ -677,18 +677,18 @@ let tests = snd xs.[2] |> equal "c" testCase "List.map3 works" <| fun () -> - let xs = [1;2;3] - let ys = [5;4;3] - let zs = [7;8;9] - let ks = List.map3 (fun x y z -> z - y - x) xs ys zs - List.sum ks - |> equal 6 + let xs = [1;2;3] + let ys = [5;4;3] + let zs = [7;8;9] + let ks = List.map3 (fun x y z -> z - y - x) xs ys zs + List.sum ks + |> equal 6 testCase "List.mapi2 works" <| fun () -> - let xs = [7;8;9] - let ys = [5;4;3] - let zs = List.mapi2 (fun i x y -> i * (x - y)) xs ys - List.sum zs |> equal 16 + let xs = [7;8;9] + let ys = [5;4;3] + let zs = List.mapi2 (fun i x y -> i * (x - y)) xs ys + List.sum zs |> equal 16 testCase "List.mapFold works" <| fun () -> let xs = [1y; 2y; 3y; 4y] @@ -714,11 +714,11 @@ let tests = equal "a" xs.Head testCase "List.partition works" <| fun () -> - let xs = [1; 2; 3; 4; 5; 6] - let ys, zs = xs |> List.partition (fun x -> x % 2 = 0) - List.sum zs |> equal 9 - equal 2 ys.[0] - equal 5 zs.[2] + let xs = [1; 2; 3; 4; 5; 6] + let ys, zs = xs |> List.partition (fun x -> x % 2 = 0) + List.sum zs |> equal 9 + equal 2 ys.[0] + equal 5 zs.[2] testCase "List.pairwise works" <| fun () -> List.pairwise [] |> equal [] @@ -731,10 +731,10 @@ let tests = |> equal "122334" testCase "List.permute works" <| fun () -> - let xs = [1; 2; 3; 4; 5; 6] - let ys = xs |> List.permute (fun i -> i + 1 - 2 * (i % 2)) - equal 4 ys.[2] - equal 6 ys.[4] + let xs = [1; 2; 3; 4; 5; 6] + let ys = xs |> List.permute (fun i -> i + 1 - 2 * (i % 2)) + equal 4 ys.[2] + equal 6 ys.[4] testCase "List.chunkBySize works" <| fun () -> [1..8] |> List.chunkBySize 4 |> equal [ [1..4]; [5..8] ] @@ -749,14 +749,14 @@ let tests = |> equal 20 testCase "List.zip3 works" <| fun () -> - let xs = [1; 2; 3] - let ys = [4; 5; 6] - let zs = [7; 8; 9] - let ks = List.zip3 xs ys zs - let x, y, z = List.last ks - equal 3 x - equal 6 y - equal 9 z + let xs = [1; 2; 3] + let ys = [4; 5; 6] + let zs = [7; 8; 9] + let ks = List.zip3 xs ys zs + let x, y, z = List.last ks + equal 3 x + equal 6 y + equal 9 z testCase "List.tryItem works" <| fun () -> let xs = [1.; 2.; 3.; 4.] @@ -820,8 +820,8 @@ let tests = List.windowed 7 nums |> List.isEmpty |> equal true testCase "Types with same name as imports work" <| fun () -> - let li = [List 5] - equal 5 li.Head.Value + let li = [List 5] + equal 5 li.Head.Value testCase "List.Item throws exception when index is out of range" <| fun () -> let xs = [0] diff --git a/tests/Js/Main/MapTests.fs b/tests/Js/Main/MapTests.fs index 611e15ba3..d98ca3eb6 100644 --- a/tests/Js/Main/MapTests.fs +++ b/tests/Js/Main/MapTests.fs @@ -291,4 +291,28 @@ let tests = |> Map.add { Bar = "a"; Foo = 10 } 2 |> Map.count |> equal 1 + + testCase "Map ICollection.IsReadOnly works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (Map xs) :> ICollection<_> + coll.IsReadOnly |> equal true + + testCase "Map ICollection.Count works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (Map xs) :> ICollection<_> + coll.Count |> equal 3 + + testCase "Map ICollection.Contains works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (Map xs) :> ICollection<_> + coll.Contains(KeyValuePair("B", 3)) |> equal false + coll.Contains(KeyValuePair("D", 3)) |> equal false + coll.Contains(KeyValuePair("B", 2)) |> equal true + + testCase "Map ICollection.CopyTo works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (Map xs) :> ICollection<_> + let ys = [| ("D", 4); ("E", 5); ("F", 6) |] |> Array.map KeyValuePair + coll.CopyTo(ys, 0) + ys = (xs |> Array.map KeyValuePair) |> equal true ] diff --git a/tests/Js/Main/ResizeArrayTests.fs b/tests/Js/Main/ResizeArrayTests.fs index 539def0b6..2abf9eb2b 100644 --- a/tests/Js/Main/ResizeArrayTests.fs +++ b/tests/Js/Main/ResizeArrayTests.fs @@ -1,5 +1,6 @@ module Fable.Tests.ResizeArrays +open System.Collections.Generic open Util.Testing type Animal = Duck of int | Dog of int @@ -299,4 +300,68 @@ let tests = myResizeArray.IndexOf(Dog 3) |> equal 1 myResizeArray.IndexOf(Dog 3, 0, 1) |> equal -1 myResizeArray.IndexOf(Duck 5, 1) |> equal -1 + + testCase "ResizeArray.CopyTo works" <| fun _ -> + let xs = ResizeArray<_> [|1;2;3;4|] + let ys = [|5;6;7;8;9|] + xs.CopyTo(ys) + ys |> equal [|1;2;3;4;9|] + + testCase "ResizeArray.CopyTo works II" <| fun _ -> + let xs = ResizeArray<_> [|1;2;3;4|] + let ys = [|5;6;7;8;9|] + xs.CopyTo(ys, 1) + ys |> equal [|5;1;2;3;4|] + + testCase "ResizeArray.CopyTo works III" <| fun _ -> + let xs = ResizeArray<_> [|1;2;3;4|] + let ys = [|5;6;7;8;9|] + xs.CopyTo(2, ys, 1, 2) + ys |> equal [|5;3;4;8;9|] + + testCase "ResizeArray ICollection.IsReadOnly works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (ResizeArray xs) :> ICollection<_> + coll.IsReadOnly |> equal false + + testCase "ResizeArray ICollection.Count works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (ResizeArray xs) :> ICollection<_> + coll.Count |> equal 3 + + testCase "ResizeArray ICollection.Contains works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (ResizeArray xs) :> ICollection<_> + coll.Contains(("B", 3)) |> equal false + coll.Contains(("D", 3)) |> equal false + coll.Contains(("B", 2)) |> equal true + + testCase "Dictionary ICollection.CopyTo works" <| fun _ -> // See #3914 + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (ResizeArray xs) :> ICollection<_> + let ys = [| ("D", 4); ("E", 5); ("F", 6) |] + coll.CopyTo(ys, 0) + ys = xs |> equal true + + testCase "ResizeArray ICollection.Clear works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (ResizeArray xs) :> ICollection<_> + coll.Clear() + coll.Count |> equal 0 + + testCase "ResizeArray ICollection.Add works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (ResizeArray xs) :> ICollection<_> + coll.Add(("A", 1)) + coll.Add(("A", 2)) + coll.Add(("D", 4)) + coll.Count |> equal 6 + + testCase "ResizeArray ICollection.Remove works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (ResizeArray xs) :> ICollection<_> + coll.Remove(("B", 3)) |> equal false + coll.Remove(("D", 3)) |> equal false + coll.Remove(("B", 2)) |> equal true + coll.Count |> equal 2 ] \ No newline at end of file diff --git a/tests/Js/Main/SetTests.fs b/tests/Js/Main/SetTests.fs index b4dc6dfbf..fd70d1ffd 100644 --- a/tests/Js/Main/SetTests.fs +++ b/tests/Js/Main/SetTests.fs @@ -1,4 +1,6 @@ module Fable.Tests.Sets + +open System.Collections.Generic open Util.Testing let tests = @@ -289,4 +291,28 @@ let tests = largeSetB.IsSupersetOf(largeSetA) |> equal true largeSetA.IsProperSubsetOf(largeSetB) |> equal false largeSetA.IsSubsetOf(largeSetB) |> equal true + + testCase "Set ICollection.IsReadOnly works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (Set xs) :> ICollection<_> + coll.IsReadOnly |> equal true + + testCase "Set ICollection.Count works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (Set xs) :> ICollection<_> + coll.Count |> equal 3 + + testCase "Set ICollection.Contains works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (Set xs) :> ICollection<_> + coll.Contains(("B", 3)) |> equal false + coll.Contains(("D", 3)) |> equal false + coll.Contains(("B", 2)) |> equal true + + testCase "Set ICollection.CopyTo works" <| fun _ -> + let xs = [| ("A", 1); ("B", 2); ("C", 3) |] + let coll = (Set xs) :> ICollection<_> + let ys = [| ("D", 4); ("E", 5); ("F", 6) |] + coll.CopyTo(ys, 0) + ys = xs |> equal true ] diff --git a/tests/Python/TestArray.fs b/tests/Python/TestArray.fs index aec03c37c..02f600a87 100644 --- a/tests/Python/TestArray.fs +++ b/tests/Python/TestArray.fs @@ -1,11 +1,10 @@ module Fable.Tests.Arrays -open System open Util.Testing open Fable.Tests.Util type ParamArrayTest = - static member Add([] xs: int[]) = Array.sum xs + static member Add([] xs: int[]) = Array.sum xs let add (xs: int[]) = ParamArrayTest.Add(xs) @@ -359,7 +358,7 @@ let ``test Array.filter works`` () = [] let ``test Array.filter with chars works`` () = let xs = [|'a'; '2'; 'b'; 'c'|] - let ys = xs |> Array.filter Char.IsLetter + let ys = xs |> Array.filter System.Char.IsLetter ys.Length |> equal 3 [] @@ -1008,17 +1007,17 @@ let ``test Testing against System.Array works`` () = zs :? System.Array |> equal false [] -let ``test Array.Copy works with numeric arrays`` () = +let ``test System.Array.Copy works with numeric arrays`` () = let source = [| 99 |] let destination = [| 1; 2; 3 |] - Array.Copy(source, 0, destination, 0, 1) + System.Array.Copy(source, 0, destination, 0, 1) equal [| 99; 2; 3 |] destination [] -let ``test Array.Copy works with non-numeric arrays`` () = +let ``test System.Array.Copy works with non-numeric arrays`` () = let source = [| "xy"; "xx"; "xyz" |] let destination = [| "a"; "b"; "c" |] - Array.Copy(source, 1, destination, 1, 2) + System.Array.Copy(source, 1, destination, 1, 2) equal [| "a"; "xx"; "xyz" |] destination [] @@ -1174,3 +1173,19 @@ let ``test Array.removeManyAt works`` () = // equal c1 true // equal c2 -1 // equal c3 1 + +// [] +// let ``test System.Array.Resize works`` () = +// let mutable xs = [|1; 2; 3; 4; 5|] +// System.Array.Resize(&xs, 3) +// xs |> equal [|1; 2; 3|] +// System.Array.Resize(&xs, 7) +// xs |> equal [|1; 2; 3; 0; 0; 0; 0|] +// System.Array.Resize(&xs, 0) +// xs |> equal [||] +// xs <- null +// System.Array.Resize(&xs, 3) +// xs |> equal [|0; 0; 0|] +// xs <- null +// System.Array.Resize(&xs, 0) +// xs |> equal [||] diff --git a/tests/Rust/tests/src/ArrayTests.fs b/tests/Rust/tests/src/ArrayTests.fs index 950f003f0..bc07b44eb 100644 --- a/tests/Rust/tests/src/ArrayTests.fs +++ b/tests/Rust/tests/src/ArrayTests.fs @@ -1291,14 +1291,14 @@ let ``Array.allPairs works`` () = // zs :? System.Array |> equal false [] -let ``Array.Copy works with numeric arrays`` () = +let ``System.Array.Copy works with numeric arrays`` () = let source = [| 99 |] let destination = [| 1; 2; 3 |] System.Array.Copy(source, 0, destination, 0, 1) equal [| 99; 2; 3 |] destination [] -let ``Array.Copy works with non-numeric arrays`` () = +let ``System.Array.Copy works with non-numeric arrays`` () = let source = [| "xy"; "xx"; "xyz" |] let destination = [| "a"; "b"; "c" |] System.Array.Copy(source, 1, destination, 1, 2) @@ -1433,3 +1433,19 @@ let ``Array.removeManyAt works`` () = throwsAnyError (fun () -> Array.removeManyAt 0 2 [||] |> ignore) throwsAnyError (fun () -> Array.removeManyAt -1 2 [|1|] |> ignore) throwsAnyError (fun () -> Array.removeManyAt 2 2 [|1|] |> ignore) + +// [] +// let ``System.Array.Resize works`` () = +// let mutable xs = [|1; 2; 3; 4; 5|] +// System.Array.Resize(&xs, 3) +// xs |> equal [|1; 2; 3|] +// System.Array.Resize(&xs, 7) +// xs |> equal [|1; 2; 3; 0; 0; 0; 0|] +// System.Array.Resize(&xs, 0) +// xs |> equal [||] +// xs <- null +// System.Array.Resize(&xs, 3) +// xs |> equal [|0; 0; 0|] +// xs <- null +// System.Array.Resize(&xs, 0) +// xs |> equal [||]