From 1a9871f1922c64a186096cf1aa8fa3068a09b0b7 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Fri, 20 Dec 2024 15:26:10 +0100 Subject: [PATCH 1/7] WIP more typechecks for deep copy --- src/DynamicObj/DynamicObj.fs | 466 +++++++++++++++++- .../CopyUtils.tryDeepCopyObj/Dictionaries.fs | 2 + .../CopyUtils.tryDeepCopyObj/DynamicObj.fs | 2 + .../DynamicObjCollections.fs | 2 + .../CopyUtils.tryDeepCopyObj/ICloneable.fs | 2 + .../CopyUtils.tryDeepCopyObj/Main.fs | 11 + .../CopyUtils.tryDeepCopyObj/Primitives.fs | 58 +++ .../CopyUtils.tryDeepCopyObj/ResizeArrays.fs | 2 + .../DynamicObject.Tests.fsproj | 7 + tests/DynamicObject.Tests/Main.fs | 1 + tests/DynamicObject.Tests/TestUtils.fs | 7 + 11 files changed, 552 insertions(+), 8 deletions(-) create mode 100644 tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs create mode 100644 tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/DynamicObj.fs create mode 100644 tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/DynamicObjCollections.fs create mode 100644 tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ICloneable.fs create mode 100644 tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Main.fs create mode 100644 tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Primitives.fs create mode 100644 tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs diff --git a/src/DynamicObj/DynamicObj.fs b/src/DynamicObj/DynamicObj.fs index a0c7276..2502739 100644 --- a/src/DynamicObj/DynamicObj.fs +++ b/src/DynamicObj/DynamicObj.fs @@ -269,6 +269,10 @@ type DynamicObj() = /// /// - Basic F# types (int, float, bool, string, char, byte, sbyte, int16, uint16, int32, uint32, int64, uint64, single, decimal) /// + /// - ResizeArrays and Dictionaries containing any combination of basic F# types + /// + /// - Dictionaries containing DynamicObj as keys or values in any combination with DynamicObj or basic F# types as keys or values + /// /// - array<DynamicObj>, list<DynamicObj>, ResizeArray<DynamicObj>: These collections of DynamicObj are copied as a new collection with recursively deep copied elements. /// /// - System.ICloneable: If the property implements ICloneable, the Clone() method is called on the property. @@ -309,6 +313,10 @@ type DynamicObj() = /// /// - Basic F# types (int, float, bool, string, char, byte, sbyte, int16, uint16, int32, uint32, int64, uint64, single, decimal) /// + /// - ResizeArrays and Dictionaries containing any combination of basic F# types + /// + /// - Dictionaries containing DynamicObj as keys or values in any combination with DynamicObj or basic F# types as keys or values + /// /// - array<DynamicObj>, list<DynamicObj>, ResizeArray<DynamicObj>: These collections of DynamicObj are copied as a new collection with recursively deep copied elements. /// /// - System.ICloneable: If the property implements ICloneable, the Clone() method is called on the property. @@ -395,11 +403,23 @@ and CopyUtils = // might be that we do not need this case, however if we remove it, some types will match the // ICloneable case in transpiled code, which we'd like to prevent, so well keep it for now. - | :? int | :? float | :? bool - | :? string | :? char | :? byte - | :? sbyte | :? int16 | :? uint16 - | :? int32 | :? uint32 | :? int64 - | :? uint64 | :? single + // https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/basic-types + | :? bool + | :? byte + | :? sbyte + | :? int16 + | :? uint16 + | :? int + | :? uint + | :? int64 + | :? uint64 + | :? nativeint + | :? unativeint + | :? float + | :? float32 + | :? char + | :? string + | :? unit -> o #if !FABLE_COMPILER_PYTHON @@ -407,12 +427,442 @@ and CopyUtils = | :? decimal -> o #endif + // ResizeArrays are mutable and we need to copy them. For primitives, we can do this easily. + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box + + // Dictionaries are mutable and we need to copy them. For primitives, we can do this easily, it is just a lot of work to write man + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + // same for dictionaries containing DynamicObj as value + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + + // And for dictionaries containing DynamicObj as key + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, kv.Value) + newDict |> box + | :? Dictionary as dict -> + let newDict = Dictionary() + for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, tryDeepCopyObj kv.Value :?> DynamicObj) + newDict |> box + + // These collections of DynamicObj can be cloned recursively + | :? ResizeArray as dyns -> + box (ResizeArray([for dyn in dyns -> tryDeepCopyObj dyn :?> DynamicObj])) | :? array as dyns -> box [|for dyn in dyns -> tryDeepCopyObj dyn :?> DynamicObj|] | :? list as dyns -> box [for dyn in dyns -> tryDeepCopyObj dyn :?> DynamicObj] - | :? ResizeArray as dyns -> - box (ResizeArray([for dyn in dyns -> tryDeepCopyObj dyn :?> DynamicObj])) + + // Fable compilable version of typematching against implemented IClonable #if FABLE_COMPILER_JAVASCRIPT || FABLE_COMPILER_TYPESCRIPT | o when FableJS.Interfaces.implementsICloneable o -> FableJS.Interfaces.cloneICloneable o #endif @@ -428,7 +878,7 @@ and CopyUtils = let newDyn = DynamicObj() // might want to keep instance props as dynamic props on copy for kv in (dyn.GetProperties(true)) do - newDyn.SetProperty(kv.Key, tryDeepCopyObj kv.Value) + newDyn.SetProperty(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) box newDyn | _ -> o diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs new file mode 100644 index 0000000..244a78a --- /dev/null +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs @@ -0,0 +1,2 @@ +module DeepCopyDictionaries + diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/DynamicObj.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/DynamicObj.fs new file mode 100644 index 0000000..16d4c78 --- /dev/null +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/DynamicObj.fs @@ -0,0 +1,2 @@ +module DeepCopyDynamicObj + diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/DynamicObjCollections.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/DynamicObjCollections.fs new file mode 100644 index 0000000..82d75b1 --- /dev/null +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/DynamicObjCollections.fs @@ -0,0 +1,2 @@ +module DeepCopyDynamicObjCollections + diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ICloneable.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ICloneable.fs new file mode 100644 index 0000000..41d05df --- /dev/null +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ICloneable.fs @@ -0,0 +1,2 @@ +module DeepCopyICloneable + diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Main.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Main.fs new file mode 100644 index 0000000..250d470 --- /dev/null +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Main.fs @@ -0,0 +1,11 @@ +module CopyUtils.Tests + +open System +open Fable.Pyxpecto +open DynamicObj +open Fable.Core + +let main = testList "CopyUtils.tryDeepCopyObj" [ + DeepCopyPrimitives.tests_DeepCopyPrimitives +] + diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Primitives.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Primitives.fs new file mode 100644 index 0000000..a80c25b --- /dev/null +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Primitives.fs @@ -0,0 +1,58 @@ +module DeepCopyPrimitives + +open System +open Fable.Pyxpecto +open DynamicObj +open Fable.Core +open TestUtils + +let tests_DeepCopyPrimitives = testList "" [ + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj true + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1uy + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1y + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1s + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1us + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1 + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1u + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1L + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1uL + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj (System.IntPtr(1)) + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj (System.UIntPtr(1u)) + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1.0 + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 1.0f + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj 'A' + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj "Hi" + Expect.equal copy original "Expected values of copy and original to be equal" + testCase "" <| fun _ -> + let original, copy = constructDeepCopiedObj () + Expect.equal copy original "Expected values of copy and original to be equal" +] \ No newline at end of file diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs new file mode 100644 index 0000000..b334ba4 --- /dev/null +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs @@ -0,0 +1,2 @@ +module DeepCopyResizeArrays + diff --git a/tests/DynamicObject.Tests/DynamicObject.Tests.fsproj b/tests/DynamicObject.Tests/DynamicObject.Tests.fsproj index 99440c8..b81ae5f 100644 --- a/tests/DynamicObject.Tests/DynamicObject.Tests.fsproj +++ b/tests/DynamicObject.Tests/DynamicObject.Tests.fsproj @@ -9,6 +9,13 @@ + + + + + + + diff --git a/tests/DynamicObject.Tests/Main.fs b/tests/DynamicObject.Tests/Main.fs index 8b79a73..0f2cf55 100644 --- a/tests/DynamicObject.Tests/Main.fs +++ b/tests/DynamicObject.Tests/Main.fs @@ -4,6 +4,7 @@ open Fable.Pyxpecto let all = testSequenced <| testList "DynamicObj" [ ReflectionUtils.Tests.main + CopyUtils.Tests.main DynamicObj.Tests.main DynObj.Tests.main Inheritance.Tests.main diff --git a/tests/DynamicObject.Tests/TestUtils.fs b/tests/DynamicObject.Tests/TestUtils.fs index 1086fc5..ab7b5db 100644 --- a/tests/DynamicObject.Tests/TestUtils.fs +++ b/tests/DynamicObject.Tests/TestUtils.fs @@ -36,6 +36,9 @@ let constructDeepCopiedClone<'T> (props: seq) = let clone = original.DeepCopyProperties() original, clone |> unbox<'T> +let constructDeepCopiedObj<'T> (original: 'T) = + original, (CopyUtils.tryDeepCopyObj original |> unbox<'T>) + let bulkMutate (props: seq) (dyn: #DynamicObj) = props |> Seq.iter (fun (propertyName, propertyValue) -> dyn.SetProperty(propertyName, propertyValue)) @@ -73,4 +76,8 @@ module Expect = let referenceEqual actual expected message = if not (LanguagePrimitives.PhysicalEquality actual expected) then + failwith message + + let notReferenceEqual actual expected message = + if (LanguagePrimitives.PhysicalEquality actual expected) then failwith message \ No newline at end of file From 7dc963870c799501216aa0c71517a2313faed2f7 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Thu, 2 Jan 2025 14:23:33 +0100 Subject: [PATCH 2/7] we must give up transpiling some typechecks, but behavbior is at least consisten in transpiled and native code --- src/DynamicObj/DynamicObj.fs | 12 +- src/DynamicObj/Playground.fsx | 45 ++++-- .../CopyUtils.tryDeepCopyObj/Primitives.fs | 36 ++--- .../CopyUtils.tryDeepCopyObj/ResizeArrays.fs | 144 ++++++++++++++++++ tests/DynamicObject.Tests/TestUtils.fs | 4 +- tests/FSharpConsole/Program.fs | 47 +++--- 6 files changed, 226 insertions(+), 62 deletions(-) diff --git a/src/DynamicObj/DynamicObj.fs b/src/DynamicObj/DynamicObj.fs index 2502739..f802a1a 100644 --- a/src/DynamicObj/DynamicObj.fs +++ b/src/DynamicObj/DynamicObj.fs @@ -413,8 +413,10 @@ and CopyUtils = | :? uint | :? int64 | :? uint64 + #if !FABLE_COMPILER | :? nativeint | :? unativeint + #endif | :? float | :? float32 | :? char @@ -427,6 +429,10 @@ and CopyUtils = | :? decimal -> o #endif + #if !FABLE_COMPILER + + // we can do some more type checking in F# land + // ResizeArrays are mutable and we need to copy them. For primitives, we can do this easily. | :? ResizeArray as r -> ResizeArray(r) |> box | :? ResizeArray as r -> ResizeArray(r) |> box @@ -632,7 +638,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box - + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -854,6 +860,8 @@ and CopyUtils = for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, tryDeepCopyObj kv.Value :?> DynamicObj) newDict |> box + #endif + // These collections of DynamicObj can be cloned recursively | :? ResizeArray as dyns -> box (ResizeArray([for dyn in dyns -> tryDeepCopyObj dyn :?> DynamicObj])) @@ -878,7 +886,7 @@ and CopyUtils = let newDyn = DynamicObj() // might want to keep instance props as dynamic props on copy for kv in (dyn.GetProperties(true)) do - newDyn.SetProperty(kv.Key, tryDeepCopyObj kv.Value :?> DynamicObj) + newDyn.SetProperty(kv.Key, tryDeepCopyObj kv.Value) box newDyn | _ -> o diff --git a/src/DynamicObj/Playground.fsx b/src/DynamicObj/Playground.fsx index 1c5f40a..f25e16d 100644 --- a/src/DynamicObj/Playground.fsx +++ b/src/DynamicObj/Playground.fsx @@ -13,18 +13,33 @@ open Fable.Pyxpecto open DynamicObj -type T(dyn:string, stat:string) as this= - inherit DynamicObj() - - do - this.SetProperty("Dyn", dyn) - - member this.Stat = stat - -let first = T("dyn1", "stat1") -let second = T("dyn2", "stat2") - -let _ = second.ShallowCopyDynamicPropertiesTo(first) - -first |> DynObj.print -second |> DynObj.print \ No newline at end of file +let constructDeepCopiedClone<'T> (props: seq) = + let original = DynamicObj() + props + |> Seq.iter (fun (propertyName, propertyValue) -> original.SetProperty(propertyName, propertyValue)) + let clone : 'T = original.DeepCopyProperties() |> unbox<'T> + original, clone + +let originalProps = [ + "int", box 1 + "float", box 1.0 + "bool", box true + "string", box "hello" + "char", box 'a' + "byte", box (byte 1) + "sbyte", box (sbyte -1) + "int16", box (int16 -1) + "uint16", box (uint16 1) + "int32", box (int32 -1) + "uint32", box (uint32 1u) + "int64", box (int64 -1L) + "uint64", box (uint64 1UL) + "single", box (single 1.0f) + "decimal", box (decimal 1M) +] +let original = DynamicObj() + +originalProps +|> Seq.iter (fun (propertyName, propertyValue) -> original.SetProperty(propertyName, propertyValue)) + +let clone = original.DeepCopyProperties() \ No newline at end of file diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Primitives.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Primitives.fs index a80c25b..f0db390 100644 --- a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Primitives.fs +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Primitives.fs @@ -6,53 +6,55 @@ open DynamicObj open Fable.Core open TestUtils -let tests_DeepCopyPrimitives = testList "" [ - testCase "" <| fun _ -> +let tests_DeepCopyPrimitives = testList "Primitives" [ + testCase "bool" <| fun _ -> let original, copy = constructDeepCopiedObj true Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "byte" <| fun _ -> let original, copy = constructDeepCopiedObj 1uy Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "sbyte" <| fun _ -> let original, copy = constructDeepCopiedObj 1y Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "int16" <| fun _ -> let original, copy = constructDeepCopiedObj 1s Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "uint16" <| fun _ -> let original, copy = constructDeepCopiedObj 1us Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "int" <| fun _ -> let original, copy = constructDeepCopiedObj 1 Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "uint" <| fun _ -> let original, copy = constructDeepCopiedObj 1u Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "int64" <| fun _ -> let original, copy = constructDeepCopiedObj 1L Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "uint64" <| fun _ -> let original, copy = constructDeepCopiedObj 1uL Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + #if !FABLE_COMPILER + testCase "nativeint" <| fun _ -> let original, copy = constructDeepCopiedObj (System.IntPtr(1)) Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "unativeint" <| fun _ -> let original, copy = constructDeepCopiedObj (System.UIntPtr(1u)) Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + #endif + testCase "float" <| fun _ -> let original, copy = constructDeepCopiedObj 1.0 Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "float32" <| fun _ -> let original, copy = constructDeepCopiedObj 1.0f Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "char" <| fun _ -> let original, copy = constructDeepCopiedObj 'A' Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "string" <| fun _ -> let original, copy = constructDeepCopiedObj "Hi" Expect.equal copy original "Expected values of copy and original to be equal" - testCase "" <| fun _ -> + testCase "unit" <| fun _ -> let original, copy = constructDeepCopiedObj () Expect.equal copy original "Expected values of copy and original to be equal" ] \ No newline at end of file diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs index b334ba4..5b45b1b 100644 --- a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs @@ -1,2 +1,146 @@ module DeepCopyResizeArrays +open System +open Fable.Pyxpecto +open DynamicObj +open Fable.Core +open TestUtils + +let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ + testCase "bool" <| fun _ -> + let arr = ResizeArray([true; false]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- false + Expect.sequenceEqual original (ResizeArray([false; false])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([true; false])) "Clone should not be affected by original mutation" + testCase "byte" <| fun _ -> + let arr = ResizeArray([1uy; 2uy]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2uy + Expect.sequenceEqual original (ResizeArray([2uy; 2uy])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1uy; 2uy])) "Clone should not be affected by original mutation" + testCase "sbyte" <| fun _ -> + let arr = ResizeArray([1y; 2y]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2y + Expect.sequenceEqual original (ResizeArray([2y; 2y])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1y; 2y])) "Clone should not be affected by original mutation" + testCase "int16" <| fun _ -> + let arr = ResizeArray([1s; 2s]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2s + Expect.sequenceEqual original (ResizeArray([2s; 2s])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1s; 2s])) "Clone should not be affected by original mutation" + testCase "uint16" <| fun _ -> + let arr = ResizeArray([1us; 2us]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2us + Expect.sequenceEqual original (ResizeArray([2us; 2us])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1us; 2us])) "Clone should not be affected by original mutation" + testCase "int" <| fun _ -> + let arr = ResizeArray([1; 2]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2 + Expect.sequenceEqual original (ResizeArray([2; 2])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1; 2])) "Clone should not be affected by original mutation" + testCase "uint" <| fun _ -> + let arr = ResizeArray([1u; 2u]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2u + Expect.sequenceEqual original (ResizeArray([2u; 2u])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1u; 2u])) "Clone should not be affected by original mutation" + testCase "int64" <| fun _ -> + let arr = ResizeArray([1L; 2L]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2L + Expect.sequenceEqual original (ResizeArray([2L; 2L])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1L; 2L])) "Clone should not be affected by original mutation" + testCase "uint64" <| fun _ -> + let arr = ResizeArray([1uL; 2uL]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2uL + Expect.sequenceEqual original (ResizeArray([2uL; 2uL])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1uL; 2uL])) "Clone should not be affected by original mutation" + testCase "float" <| fun _ -> + let arr = ResizeArray([1.0; 2.0]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2.0 + Expect.sequenceEqual original (ResizeArray([2.0; 2.0])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1.0; 2.0])) "Clone should not be affected by original mutation" + testCase "float32" <| fun _ -> + let arr = ResizeArray([1.0f; 2.0f]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2.0f + Expect.sequenceEqual original (ResizeArray([2.0f; 2.0f])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1.0f; 2.0f])) "Clone should not be affected by original mutation" + testCase "char" <| fun _ -> + let arr = ResizeArray(['A'; 'B']) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 'B' + Expect.sequenceEqual original (ResizeArray(['B'; 'B'])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray(['A'; 'B'])) "Clone should not be affected by original mutation" + testCase "string" <| fun _ -> + let arr = ResizeArray(["Hi"; "Bye"]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- "Bye" + Expect.sequenceEqual original (ResizeArray(["Bye"; "Bye"])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray(["Hi"; "Bye"])) "Clone should not be affected by original mutation" + testCase "unit" <| fun _ -> + let arr = ResizeArray([(); ()]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr.Add(()) + Expect.sequenceEqual original (ResizeArray([(); (); ()])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([(); ()])) "Clone should not be affected by original mutation" + + // some cases are not transpilable + + #if !FABLE_COMPILER_PYTHON + testCase "decimal" <| fun _ -> + let arr = ResizeArray([1.0M; 2.0M]) + let original, copy = constructDeepCopiedObj arr + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + arr[0] <- 2.0M + Expect.sequenceEqual original (ResizeArray([2.0M; 2.0M])) "Original schould have been mutated" + Expect.sequenceEqual copy (ResizeArray([1.0M; 2.0M])) "Clone should not be affected by original mutation" + #endif + + #if !FABLE_COMPILER + testCase "nativeint" <| fun _ -> + let original, copy = constructDeepCopiedObj (ResizeArray([System.IntPtr(1); System.IntPtr(2)])) + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + testCase "unativeint" <| fun _ -> + let original, copy = constructDeepCopiedObj (ResizeArray([System.UIntPtr(1u); System.UIntPtr(2u)])) + Expect.equal copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + #endif +] \ No newline at end of file diff --git a/tests/DynamicObject.Tests/TestUtils.fs b/tests/DynamicObject.Tests/TestUtils.fs index ab7b5db..c118b5d 100644 --- a/tests/DynamicObject.Tests/TestUtils.fs +++ b/tests/DynamicObject.Tests/TestUtils.fs @@ -33,8 +33,8 @@ let constructDeepCopiedClone<'T> (props: seq) = let original = DynamicObj() props |> Seq.iter (fun (propertyName, propertyValue) -> original.SetProperty(propertyName, propertyValue)) - let clone = original.DeepCopyProperties() - original, clone |> unbox<'T> + let clone : 'T = original.DeepCopyProperties() |> unbox<'T> + original, clone let constructDeepCopiedObj<'T> (original: 'T) = original, (CopyUtils.tryDeepCopyObj original |> unbox<'T>) diff --git a/tests/FSharpConsole/Program.fs b/tests/FSharpConsole/Program.fs index 68e5933..cd3dcc9 100644 --- a/tests/FSharpConsole/Program.fs +++ b/tests/FSharpConsole/Program.fs @@ -1,30 +1,25 @@ -// For more information see https://aka.ms/fsharp-console-apps +open DynamicObj -open DynamicObj +let constructDeepCopiedClone<'T> (props: seq) = + let original = DynamicObj() + props + |> Seq.iter (fun (propertyName, propertyValue) -> original.SetProperty(propertyName, propertyValue)) + let clone : 'T = original.DeepCopyProperties() |> unbox<'T> + original, clone -type Inner() = - inherit DynamicObj() - static member init( - ?inner_value: string - ) = - Inner() - |> DynObj.withOptionalProperty "inner_value" inner_value +let item1 = DynamicObj() |> DynObj.withProperty "item" 1 +let item2 = DynamicObj() |> DynObj.withProperty "item" 2 +let item3 = DynamicObj() |> DynObj.withProperty "item" 3 +let arr = [|item1; item2; item3|] +let original, clone = constructDeepCopiedClone ["arr", box arr] +item1.SetProperty("item", -1) +item2.SetProperty("item", -1) +item3.SetProperty("item", -1) -type Outer() = - inherit DynamicObj() - static member init( - ?A: int, - ?B: string, - ?Inner: Inner - ) = - Outer() - |> DynObj.withOptionalProperty "A" A - |> DynObj.withOptionalProperty "B" B - |> DynObj.withOptionalProperty "Inner" Inner +original +|> DynObj.tryGetTypedPropertyValue "arr" +|> Option.iter (Seq.iter DynObj.print) - -let outer1 = Outer.init(A = 1, B = "first", Inner = Inner.init(inner_value = "inner_first")) -let outer2 = Outer.init(A = 2, B = "second", Inner = Inner.init(inner_value = "inner_second")) -let expected = Outer.init(A = 2, B = "second", Inner = Inner.init(inner_value = "inner_second")) - -printfn "%A" ((DynObj.combine outer1 outer2) = expected) \ No newline at end of file +clone +|> DynObj.tryGetTypedPropertyValue "arr" +|> Option.iter (Seq.iter DynObj.print) \ No newline at end of file From af340c6197b4ae94f29fa678abc717f1f4de0ea0 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Fri, 3 Jan 2025 15:16:40 +0100 Subject: [PATCH 3/7] fix structural equality tests, conditional dictionary typechecks --- src/DynamicObj/DynamicObj.fs | 69 ++++++++++++++++++- src/DynamicObj/FableJS.fs | 7 ++ src/DynamicObj/FablePy.fs | 6 ++ src/DynamicObj/Playground.fsx | 35 ++-------- .../CopyUtils.tryDeepCopyObj/Dictionaries.fs | 20 ++++++ .../CopyUtils.tryDeepCopyObj/Main.fs | 2 + .../CopyUtils.tryDeepCopyObj/ResizeArrays.fs | 38 +++++----- tests/DynamicObject.Tests/TestUtils.fs | 21 +++++- 8 files changed, 148 insertions(+), 50 deletions(-) diff --git a/src/DynamicObj/DynamicObj.fs b/src/DynamicObj/DynamicObj.fs index f802a1a..03b8153 100644 --- a/src/DynamicObj/DynamicObj.fs +++ b/src/DynamicObj/DynamicObj.fs @@ -267,7 +267,7 @@ type DynamicObj() = /// /// The following cases are handled (in this precedence): /// - /// - Basic F# types (int, float, bool, string, char, byte, sbyte, int16, uint16, int32, uint32, int64, uint64, single, decimal) + /// - Basic F# types (bool, byte, sbyte, int16, uint16, int, uint, int64, uint64, nativeint, unativeint, float, float32, char, string, unit, decimal) /// /// - ResizeArrays and Dictionaries containing any combination of basic F# types /// @@ -311,7 +311,7 @@ type DynamicObj() = /// /// The following cases are handled (in this precedence): /// - /// - Basic F# types (int, float, bool, string, char, byte, sbyte, int16, uint16, int32, uint32, int64, uint64, single, decimal) + /// - Basic F# types (bool, byte, sbyte, int16, uint16, int, uint, int64, uint64, nativeint, unativeint, float, float32, char, string, unit, decimal) /// /// - ResizeArrays and Dictionaries containing any combination of basic F# types /// @@ -433,6 +433,10 @@ and CopyUtils = // we can do some more type checking in F# land + // ResizeArray typematches are all translated as `isArrayLike` in Fable JS/Py, so all these cases are the same in transpiled code. + // However this is fine, as we can transpile one single case (the `ResizeArray` case) that recursively applies `tryDeepCopyObj` on all items. + // That way, everything is fine in the untyped world, and we can keep the boxed types in F#. + // ResizeArrays are mutable and we need to copy them. For primitives, we can do this easily. | :? ResizeArray as r -> ResizeArray(r) |> box | :? ResizeArray as r -> ResizeArray(r) |> box @@ -450,8 +454,10 @@ and CopyUtils = | :? ResizeArray as r -> ResizeArray(r) |> box | :? ResizeArray as r -> ResizeArray(r) |> box | :? ResizeArray as r -> ResizeArray(r) |> box + | :? ResizeArray as r -> ResizeArray(r) |> box // Dictionaries are mutable and we need to copy them. For primitives, we can do this easily, it is just a lot of work to write man + // Fable does simply not compile these typechecks, i guess because everything is an object/dictionary in JS/PY. | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -468,6 +474,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -485,6 +492,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -502,6 +510,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -519,6 +528,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -536,6 +546,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -553,6 +564,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -570,6 +582,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -587,6 +600,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -604,6 +618,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -621,6 +636,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -638,6 +654,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -655,6 +672,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -672,6 +690,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -689,6 +708,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -706,6 +726,7 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box @@ -723,6 +744,25 @@ and CopyUtils = | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box + | :? Dictionary as dict -> Dictionary(dict) |> box // same for dictionaries containing DynamicObj as value | :? Dictionary as dict -> @@ -859,14 +899,39 @@ and CopyUtils = let newDict = Dictionary() for kv in dict do newDict.Add(tryDeepCopyObj kv.Key :?> DynamicObj, tryDeepCopyObj kv.Value :?> DynamicObj) newDict |> box + #endif + + // native fallbacks for matching Map/dict, see https://github.com/CSBiology/DynamicObj/issues/47 + #if FABLE_COMPILER_JAVASCRIPT || FABLE_COMPILER_TYPESCRIPT + | o when FableJS.Dictionaries.isMap o -> + let o = o |> unbox> + let newDict = Dictionary() + for kv in o do newDict.Add(tryDeepCopyObj kv.Key, tryDeepCopyObj kv.Value) + newDict |> box + | o when FableJS.Dictionaries.isMap o -> + let o = o |> unbox> + let newDict = Dictionary() + for kv in o do newDict.Add(tryDeepCopyObj kv.Key, tryDeepCopyObj kv.Value) + newDict |> box + #endif + #if FABLE_COMPILER_PYTHON + // https://github.com/fable-compiler/Fable/issues/3972 + | o when FablePy.Dictionaries.isDict o -> + let o = o |> unbox> + let newDict = Dictionary() + for kv in o do newDict.Add(tryDeepCopyObj kv.Key, tryDeepCopyObj kv.Value) + newDict |> box #endif // These collections of DynamicObj can be cloned recursively | :? ResizeArray as dyns -> box (ResizeArray([for dyn in dyns -> tryDeepCopyObj dyn :?> DynamicObj])) + #if !FABLE_COMPILER + // this gets compiled to isArrayLike just the same as ResizeArray, but generates a slightly different result handling, so we only transpile the above. | :? array as dyns -> box [|for dyn in dyns -> tryDeepCopyObj dyn :?> DynamicObj|] + #endif | :? list as dyns -> box [for dyn in dyns -> tryDeepCopyObj dyn :?> DynamicObj] diff --git a/src/DynamicObj/FableJS.fs b/src/DynamicObj/FableJS.fs index ff457ff..16c384e 100644 --- a/src/DynamicObj/FableJS.fs +++ b/src/DynamicObj/FableJS.fs @@ -168,4 +168,11 @@ module FableJS = let cloneICloneable (o:obj) : obj = jsNative + module Dictionaries = + [] + let isMap (o:obj) : bool = + jsNative + [] + let isDict (o:obj) : bool = + jsNative #endif \ No newline at end of file diff --git a/src/DynamicObj/FablePy.fs b/src/DynamicObj/FablePy.fs index 1bc575e..ceb22a7 100644 --- a/src/DynamicObj/FablePy.fs +++ b/src/DynamicObj/FablePy.fs @@ -220,4 +220,10 @@ module FablePy = [] let cloneICloneable (o:obj) : obj = nativeOnly + + module Dictionaries = + [] + let isDict (o:obj) : bool = + nativeOnly + #endif \ No newline at end of file diff --git a/src/DynamicObj/Playground.fsx b/src/DynamicObj/Playground.fsx index f25e16d..a98a44c 100644 --- a/src/DynamicObj/Playground.fsx +++ b/src/DynamicObj/Playground.fsx @@ -13,33 +13,10 @@ open Fable.Pyxpecto open DynamicObj -let constructDeepCopiedClone<'T> (props: seq) = - let original = DynamicObj() - props - |> Seq.iter (fun (propertyName, propertyValue) -> original.SetProperty(propertyName, propertyValue)) - let clone : 'T = original.DeepCopyProperties() |> unbox<'T> - original, clone +let r1 = ResizeArray([1; 2]) +let r2 = ResizeArray([1; 2]) +let r3 = r1 -let originalProps = [ - "int", box 1 - "float", box 1.0 - "bool", box true - "string", box "hello" - "char", box 'a' - "byte", box (byte 1) - "sbyte", box (sbyte -1) - "int16", box (int16 -1) - "uint16", box (uint16 1) - "int32", box (int32 -1) - "uint32", box (uint32 1u) - "int64", box (int64 -1L) - "uint64", box (uint64 1UL) - "single", box (single 1.0f) - "decimal", box (decimal 1M) -] -let original = DynamicObj() - -originalProps -|> Seq.iter (fun (propertyName, propertyValue) -> original.SetProperty(propertyName, propertyValue)) - -let clone = original.DeepCopyProperties() \ No newline at end of file +printfn "%A" (LanguagePrimitives.PhysicalEquality r1 r2) +printfn "%A" (LanguagePrimitives.PhysicalEquality r2 r2) +printfn "%A" (LanguagePrimitives.PhysicalEquality r3 r1) \ No newline at end of file diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs index 244a78a..77a2c98 100644 --- a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs @@ -1,2 +1,22 @@ module DeepCopyDictionaries +open System +open Fable.Pyxpecto +open DynamicObj +open Fable.Core +open TestUtils +open System.Collections.Generic + +let tests_DeepCopyDictionaries = testList "Dictionaries" [ +// there are hundreds of potential test cases here for each type combination + testCase "string, string" <| fun _ -> + let d = new Dictionary() + d.Add("k1", "v1") + d.Add("k2", "v2") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["k1"] <- "mutated" + Expect.sequenceEqual original (dict [ "k1", "mutated"; "k2", "v2" ]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [ "k1", "v1"; "k2", "v2" ]) "Clone should not be affected by original mutation" +] \ No newline at end of file diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Main.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Main.fs index 250d470..593626e 100644 --- a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Main.fs +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Main.fs @@ -7,5 +7,7 @@ open Fable.Core let main = testList "CopyUtils.tryDeepCopyObj" [ DeepCopyPrimitives.tests_DeepCopyPrimitives + DeepCopyResizeArrays.tests_DeepCopyResizeArrays + DeepCopyDictionaries.tests_DeepCopyDictionaries ] diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs index 5b45b1b..a892b2b 100644 --- a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/ResizeArrays.fs @@ -10,7 +10,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "bool" <| fun _ -> let arr = ResizeArray([true; false]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- false Expect.sequenceEqual original (ResizeArray([false; false])) "Original schould have been mutated" @@ -18,7 +18,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "byte" <| fun _ -> let arr = ResizeArray([1uy; 2uy]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2uy Expect.sequenceEqual original (ResizeArray([2uy; 2uy])) "Original schould have been mutated" @@ -26,7 +26,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "sbyte" <| fun _ -> let arr = ResizeArray([1y; 2y]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2y Expect.sequenceEqual original (ResizeArray([2y; 2y])) "Original schould have been mutated" @@ -34,7 +34,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "int16" <| fun _ -> let arr = ResizeArray([1s; 2s]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2s Expect.sequenceEqual original (ResizeArray([2s; 2s])) "Original schould have been mutated" @@ -42,7 +42,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "uint16" <| fun _ -> let arr = ResizeArray([1us; 2us]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2us Expect.sequenceEqual original (ResizeArray([2us; 2us])) "Original schould have been mutated" @@ -50,7 +50,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "int" <| fun _ -> let arr = ResizeArray([1; 2]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2 Expect.sequenceEqual original (ResizeArray([2; 2])) "Original schould have been mutated" @@ -58,7 +58,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "uint" <| fun _ -> let arr = ResizeArray([1u; 2u]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2u Expect.sequenceEqual original (ResizeArray([2u; 2u])) "Original schould have been mutated" @@ -66,7 +66,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "int64" <| fun _ -> let arr = ResizeArray([1L; 2L]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2L Expect.sequenceEqual original (ResizeArray([2L; 2L])) "Original schould have been mutated" @@ -74,7 +74,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "uint64" <| fun _ -> let arr = ResizeArray([1uL; 2uL]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2uL Expect.sequenceEqual original (ResizeArray([2uL; 2uL])) "Original schould have been mutated" @@ -82,7 +82,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "float" <| fun _ -> let arr = ResizeArray([1.0; 2.0]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2.0 Expect.sequenceEqual original (ResizeArray([2.0; 2.0])) "Original schould have been mutated" @@ -90,7 +90,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "float32" <| fun _ -> let arr = ResizeArray([1.0f; 2.0f]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2.0f Expect.sequenceEqual original (ResizeArray([2.0f; 2.0f])) "Original schould have been mutated" @@ -98,7 +98,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "char" <| fun _ -> let arr = ResizeArray(['A'; 'B']) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 'B' Expect.sequenceEqual original (ResizeArray(['B'; 'B'])) "Original schould have been mutated" @@ -106,7 +106,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "string" <| fun _ -> let arr = ResizeArray(["Hi"; "Bye"]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- "Bye" Expect.sequenceEqual original (ResizeArray(["Bye"; "Bye"])) "Original schould have been mutated" @@ -114,9 +114,11 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "unit" <| fun _ -> let arr = ResizeArray([(); ()]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" - arr.Add(()) + // transpilation fun + let arr2 = ResizeArray([()]) + arr.Add(arr2[0]) Expect.sequenceEqual original (ResizeArray([(); (); ()])) "Original schould have been mutated" Expect.sequenceEqual copy (ResizeArray([(); ()])) "Clone should not be affected by original mutation" @@ -126,7 +128,7 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ testCase "decimal" <| fun _ -> let arr = ResizeArray([1.0M; 2.0M]) let original, copy = constructDeepCopiedObj arr - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" arr[0] <- 2.0M Expect.sequenceEqual original (ResizeArray([2.0M; 2.0M])) "Original schould have been mutated" @@ -136,11 +138,11 @@ let tests_DeepCopyResizeArrays = testList "ResizeArrays" [ #if !FABLE_COMPILER testCase "nativeint" <| fun _ -> let original, copy = constructDeepCopiedObj (ResizeArray([System.IntPtr(1); System.IntPtr(2)])) - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" testCase "unativeint" <| fun _ -> let original, copy = constructDeepCopiedObj (ResizeArray([System.UIntPtr(1u); System.UIntPtr(2u)])) - Expect.equal copy original "Expected values of copy and original to be equal" + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" #endif ] \ No newline at end of file diff --git a/tests/DynamicObject.Tests/TestUtils.fs b/tests/DynamicObject.Tests/TestUtils.fs index c118b5d..62b6d1f 100644 --- a/tests/DynamicObject.Tests/TestUtils.fs +++ b/tests/DynamicObject.Tests/TestUtils.fs @@ -59,6 +59,13 @@ module DynObj = | _ -> failwith "Empty property list" getProp dyn props +#if FABLE_COMPILER_PYTHON +module Py = + [] + let isReferenceEqual o1 o2 : bool = + nativeOnly +#endif + module Expect = /// Expects the `actual` sequence to equal the `expected` one. let sequenceEqual actual expected message = @@ -74,10 +81,22 @@ module Expect = failwithf "%s. Sequence actual longer than expected, at pos %i found item %O." message i a + + let referenceEqual actual expected message = + #if FABLE_COMPILER_PYTHON + if not (Py.isReferenceEqual actual expected) then + failwith message + #else if not (LanguagePrimitives.PhysicalEquality actual expected) then failwith message + #endif let notReferenceEqual actual expected message = + #if FABLE_COMPILER_PYTHON + if (Py.isReferenceEqual actual expected) then + failwith message + #else if (LanguagePrimitives.PhysicalEquality actual expected) then - failwith message \ No newline at end of file + failwith message + #endif \ No newline at end of file From 66b31bda83beab1cbff57aa86302b1c7d64551bc Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Mon, 6 Jan 2025 13:29:36 +0100 Subject: [PATCH 4/7] add some dictionary deep copy tests --- .../CopyUtils.tryDeepCopyObj/Dictionaries.fs | 380 +++++++++++++++++- 1 file changed, 370 insertions(+), 10 deletions(-) diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs index 77a2c98..e7c3f6b 100644 --- a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs @@ -9,14 +9,374 @@ open System.Collections.Generic let tests_DeepCopyDictionaries = testList "Dictionaries" [ // there are hundreds of potential test cases here for each type combination - testCase "string, string" <| fun _ -> - let d = new Dictionary() - d.Add("k1", "v1") - d.Add("k2", "v2") - let original, copy = constructDeepCopiedObj d - Expect.sequenceEqual copy original "Expected values of copy and original to be equal" - Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" - d.["k1"] <- "mutated" - Expect.sequenceEqual original (dict [ "k1", "mutated"; "k2", "v2" ]) "Original schould have been mutated" - Expect.sequenceEqual copy (dict [ "k1", "v1"; "k2", "v2" ]) "Clone should not be affected by original mutation" + testList "bool keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(true, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- false + Expect.sequenceEqual original (dict [true, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2uy + Expect.sequenceEqual original (dict [true, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2y + Expect.sequenceEqual original (dict [true, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2s + Expect.sequenceEqual original (dict [true, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2us + Expect.sequenceEqual original (dict [true, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2 + Expect.sequenceEqual original (dict [true, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2u + Expect.sequenceEqual original (dict [true, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2L + Expect.sequenceEqual original (dict [true, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2uL + Expect.sequenceEqual original (dict [true, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2.0 + Expect.sequenceEqual original (dict [true, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2.0f + Expect.sequenceEqual original (dict [true, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 'B' + Expect.sequenceEqual original (dict [true, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(true, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- "k2" + Expect.sequenceEqual original (dict [true, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(true, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(false,()) + Expect.sequenceEqual original (dict [true, (); false, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(true, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- 2.0M + Expect.sequenceEqual original (dict [true, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(true, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [true, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(true, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[true] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [true, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [true, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "byte keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- false + Expect.sequenceEqual original (dict [1uy, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2uy + Expect.sequenceEqual original (dict [1uy, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2y + Expect.sequenceEqual original (dict [1uy, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2s + Expect.sequenceEqual original (dict [1uy, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2us + Expect.sequenceEqual original (dict [1uy, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2 + Expect.sequenceEqual original (dict [1uy, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2u + Expect.sequenceEqual original (dict [1uy, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2L + Expect.sequenceEqual original (dict [1uy, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2uL + Expect.sequenceEqual original (dict [1uy, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2.0 + Expect.sequenceEqual original (dict [1uy, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2.0f + Expect.sequenceEqual original (dict [1uy, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 'B' + Expect.sequenceEqual original (dict [1uy, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- "k2" + Expect.sequenceEqual original (dict [1uy, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2uy,()) + Expect.sequenceEqual original (dict [1uy, (); 2uy, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- 2.0M + Expect.sequenceEqual original (dict [1uy, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1uy, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1uy, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uy] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1uy, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uy, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + //testList "byte keys" [ + + //] + //testList "sbyte keys" [ + + //] + //testList "int16 keys" [ + + //] + //testList "uint16 keys" [ + + //] + //testList "int keys" [ + + //] + //testList "uint keys" [ + + //] + //testList "int64 keys" [ + + //] + //testList "uint64 keys" [ + + //] + //testList "float keys" [ + + //] + //testList "float32 keys" [ + + //] + //testList "char keys" [ + + //] + //testList "string keys" [ + + //] + //testList "unit keys" [ + + //] + #if !FABLE_COMPILER_PYTHON + //testList "decimal keys" [ + + //] + #endif + #if !FABLE_COMPILER + //testList "nativeint keys" [ + + //] + //testList "unativeint keys" [ + + //] + #endif ] \ No newline at end of file From 7144ee85b081b25ee4f5ac8d6546fbe05a976557 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Mon, 6 Jan 2025 13:36:08 +0100 Subject: [PATCH 5/7] ?? --- tests/CSharpTests/CSharpTests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/CSharpTests/CSharpTests.csproj b/tests/CSharpTests/CSharpTests.csproj index faf0826..ddf25ca 100644 --- a/tests/CSharpTests/CSharpTests.csproj +++ b/tests/CSharpTests/CSharpTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 false From 311d17c532983725cc26cdda107d3bdf5ed65746 Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Fri, 24 Jan 2025 10:38:31 +0100 Subject: [PATCH 6/7] Add tests for deep copying all supported dictionaries --- src/DynamicObj/DynamicObj.fs | 2 +- .../CopyUtils.tryDeepCopyObj/Dictionaries.fs | 2273 ++++++++++++++++- 2 files changed, 2228 insertions(+), 47 deletions(-) diff --git a/src/DynamicObj/DynamicObj.fs b/src/DynamicObj/DynamicObj.fs index 03b8153..b0f70a8 100644 --- a/src/DynamicObj/DynamicObj.fs +++ b/src/DynamicObj/DynamicObj.fs @@ -909,7 +909,7 @@ and CopyUtils = let newDict = Dictionary() for kv in o do newDict.Add(tryDeepCopyObj kv.Key, tryDeepCopyObj kv.Value) newDict |> box - | o when FableJS.Dictionaries.isMap o -> + | o when FableJS.Dictionaries.isDict o -> let o = o |> unbox> let newDict = Dictionary() for kv in o do newDict.Add(tryDeepCopyObj kv.Key, tryDeepCopyObj kv.Value) diff --git a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs index e7c3f6b..8011179 100644 --- a/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs +++ b/tests/DynamicObject.Tests/CopyUtils.tryDeepCopyObj/Dictionaries.fs @@ -327,56 +327,2237 @@ let tests_DeepCopyDictionaries = testList "Dictionaries" [ Expect.sequenceEqual copy (dict [1uy, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" #endif ] - //testList "byte keys" [ - - //] - //testList "sbyte keys" [ - - //] - //testList "int16 keys" [ - - //] - //testList "uint16 keys" [ - - //] - //testList "int keys" [ - - //] - //testList "uint keys" [ - - //] - //testList "int64 keys" [ - - //] - //testList "uint64 keys" [ - - //] - //testList "float keys" [ - - //] - //testList "float32 keys" [ - - //] - //testList "char keys" [ - - //] - //testList "string keys" [ - - //] + testList "sbyte keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- false + Expect.sequenceEqual original (dict [1y, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2uy + Expect.sequenceEqual original (dict [1y, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2y + Expect.sequenceEqual original (dict [1y, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2s + Expect.sequenceEqual original (dict [1y, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2us + Expect.sequenceEqual original (dict [1y, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2 + Expect.sequenceEqual original (dict [1y, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2u + Expect.sequenceEqual original (dict [1y, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2L + Expect.sequenceEqual original (dict [1y, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2uL + Expect.sequenceEqual original (dict [1y, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2.0 + Expect.sequenceEqual original (dict [1y, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2.0f + Expect.sequenceEqual original (dict [1y, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 'B' + Expect.sequenceEqual original (dict [1y, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- "k2" + Expect.sequenceEqual original (dict [1y, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2y,()) + Expect.sequenceEqual original (dict [1y, (); 2y, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- 2.0M + Expect.sequenceEqual original (dict [1y, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1y, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1y, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1y] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1y, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1y, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "int16 keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- false + Expect.sequenceEqual original (dict [1s, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2uy + Expect.sequenceEqual original (dict [1s, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2y + Expect.sequenceEqual original (dict [1s, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2s + Expect.sequenceEqual original (dict [1s, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2us + Expect.sequenceEqual original (dict [1s, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2 + Expect.sequenceEqual original (dict [1s, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2u + Expect.sequenceEqual original (dict [1s, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2L + Expect.sequenceEqual original (dict [1s, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2uL + Expect.sequenceEqual original (dict [1s, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2.0 + Expect.sequenceEqual original (dict [1s, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2.0f + Expect.sequenceEqual original (dict [1s, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 'B' + Expect.sequenceEqual original (dict [1s, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- "k2" + Expect.sequenceEqual original (dict [1s, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2s,()) + Expect.sequenceEqual original (dict [1s, (); 2s, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- 2.0M + Expect.sequenceEqual original (dict [1s, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1s, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1s, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1s] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1s, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1s, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "uint16 keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- false + Expect.sequenceEqual original (dict [1us, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2uy + Expect.sequenceEqual original (dict [1us, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2y + Expect.sequenceEqual original (dict [1us, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2s + Expect.sequenceEqual original (dict [1us, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2us + Expect.sequenceEqual original (dict [1us, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2 + Expect.sequenceEqual original (dict [1us, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2u + Expect.sequenceEqual original (dict [1us, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2L + Expect.sequenceEqual original (dict [1us, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2uL + Expect.sequenceEqual original (dict [1us, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2.0 + Expect.sequenceEqual original (dict [1us, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2.0f + Expect.sequenceEqual original (dict [1us, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 'B' + Expect.sequenceEqual original (dict [1us, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- "k2" + Expect.sequenceEqual original (dict [1us, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2us,()) + Expect.sequenceEqual original (dict [1us, (); 2us, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- 2.0M + Expect.sequenceEqual original (dict [1us, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1us, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1us, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1us] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1us, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1us, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "int keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- false + Expect.sequenceEqual original (dict [1, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2uy + Expect.sequenceEqual original (dict [1, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2y + Expect.sequenceEqual original (dict [1, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2s + Expect.sequenceEqual original (dict [1, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2us + Expect.sequenceEqual original (dict [1, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2 + Expect.sequenceEqual original (dict [1, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2u + Expect.sequenceEqual original (dict [1, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2L + Expect.sequenceEqual original (dict [1, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2uL + Expect.sequenceEqual original (dict [1, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2.0 + Expect.sequenceEqual original (dict [1, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2.0f + Expect.sequenceEqual original (dict [1, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 'B' + Expect.sequenceEqual original (dict [1, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- "k2" + Expect.sequenceEqual original (dict [1, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2,()) + Expect.sequenceEqual original (dict [1, (); 2, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- 2.0M + Expect.sequenceEqual original (dict [1, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "uint keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- false + Expect.sequenceEqual original (dict [1u, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2uy + Expect.sequenceEqual original (dict [1u, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2y + Expect.sequenceEqual original (dict [1u, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2s + Expect.sequenceEqual original (dict [1u, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2us + Expect.sequenceEqual original (dict [1u, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2 + Expect.sequenceEqual original (dict [1u, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2u + Expect.sequenceEqual original (dict [1u, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2L + Expect.sequenceEqual original (dict [1u, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2uL + Expect.sequenceEqual original (dict [1u, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2.0 + Expect.sequenceEqual original (dict [1u, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2.0f + Expect.sequenceEqual original (dict [1u, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 'B' + Expect.sequenceEqual original (dict [1u, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- "k2" + Expect.sequenceEqual original (dict [1u, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2u,()) + Expect.sequenceEqual original (dict [1u, (); 2u, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- 2.0M + Expect.sequenceEqual original (dict [1u, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1u, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1u, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1u] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1u, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1u, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "int64 keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- false + Expect.sequenceEqual original (dict [1L, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2uy + Expect.sequenceEqual original (dict [1L, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2y + Expect.sequenceEqual original (dict [1L, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2s + Expect.sequenceEqual original (dict [1L, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2us + Expect.sequenceEqual original (dict [1L, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2 + Expect.sequenceEqual original (dict [1L, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2u + Expect.sequenceEqual original (dict [1L, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2L + Expect.sequenceEqual original (dict [1L, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2uL + Expect.sequenceEqual original (dict [1L, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2.0 + Expect.sequenceEqual original (dict [1L, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2.0f + Expect.sequenceEqual original (dict [1L, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 'B' + Expect.sequenceEqual original (dict [1L, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- "k2" + Expect.sequenceEqual original (dict [1L, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2L,()) + Expect.sequenceEqual original (dict [1L, (); 2L, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- 2.0M + Expect.sequenceEqual original (dict [1L, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1L, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1L, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1L] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1L, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1L, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "uint64 keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- false + Expect.sequenceEqual original (dict [1uL, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2uy + Expect.sequenceEqual original (dict [1uL, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2y + Expect.sequenceEqual original (dict [1uL, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2s + Expect.sequenceEqual original (dict [1uL, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2us + Expect.sequenceEqual original (dict [1uL, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2 + Expect.sequenceEqual original (dict [1uL, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2u + Expect.sequenceEqual original (dict [1uL, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2L + Expect.sequenceEqual original (dict [1uL, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2uL + Expect.sequenceEqual original (dict [1uL, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2.0 + Expect.sequenceEqual original (dict [1uL, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2.0f + Expect.sequenceEqual original (dict [1uL, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 'B' + Expect.sequenceEqual original (dict [1uL, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- "k2" + Expect.sequenceEqual original (dict [1uL, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2uL,()) + Expect.sequenceEqual original (dict [1uL, (); 2uL, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- 2.0M + Expect.sequenceEqual original (dict [1uL, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1uL, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1uL, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1uL] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1uL, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1uL, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "float keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- false + Expect.sequenceEqual original (dict [1.0, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2uy + Expect.sequenceEqual original (dict [1.0, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2y + Expect.sequenceEqual original (dict [1.0, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2s + Expect.sequenceEqual original (dict [1.0, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2us + Expect.sequenceEqual original (dict [1.0, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2 + Expect.sequenceEqual original (dict [1.0, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2u + Expect.sequenceEqual original (dict [1.0, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2L + Expect.sequenceEqual original (dict [1.0, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2uL + Expect.sequenceEqual original (dict [1.0, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2.0 + Expect.sequenceEqual original (dict [1.0, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2.0f + Expect.sequenceEqual original (dict [1.0, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 'B' + Expect.sequenceEqual original (dict [1.0, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- "k2" + Expect.sequenceEqual original (dict [1.0, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2.0,()) + Expect.sequenceEqual original (dict [1.0, (); 2.0, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- 2.0M + Expect.sequenceEqual original (dict [1.0, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1.0, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1.0, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "float32 keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- false + Expect.sequenceEqual original (dict [1.0f, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2uy + Expect.sequenceEqual original (dict [1.0f, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2y + Expect.sequenceEqual original (dict [1.0f, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2s + Expect.sequenceEqual original (dict [1.0f, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2us + Expect.sequenceEqual original (dict [1.0f, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2 + Expect.sequenceEqual original (dict [1.0f, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2u + Expect.sequenceEqual original (dict [1.0f, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2L + Expect.sequenceEqual original (dict [1.0f, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2uL + Expect.sequenceEqual original (dict [1.0f, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2.0 + Expect.sequenceEqual original (dict [1.0f, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2.0f + Expect.sequenceEqual original (dict [1.0f, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 'B' + Expect.sequenceEqual original (dict [1.0f, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- "k2" + Expect.sequenceEqual original (dict [1.0f, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2.0f,()) + Expect.sequenceEqual original (dict [1.0f, (); 2.0f, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- 2.0M + Expect.sequenceEqual original (dict [1.0f, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1.0f, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0f, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0f] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1.0f, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0f, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "char keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add('A', true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- false + Expect.sequenceEqual original (dict ['A', false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2uy + Expect.sequenceEqual original (dict ['A', 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2y + Expect.sequenceEqual original (dict ['A', 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2s + Expect.sequenceEqual original (dict ['A', 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2us + Expect.sequenceEqual original (dict ['A', 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2 + Expect.sequenceEqual original (dict ['A', 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2u + Expect.sequenceEqual original (dict ['A', 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2L + Expect.sequenceEqual original (dict ['A', 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2uL + Expect.sequenceEqual original (dict ['A', 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2.0 + Expect.sequenceEqual original (dict ['A', 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2.0f + Expect.sequenceEqual original (dict ['A', 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 'B' + Expect.sequenceEqual original (dict ['A', 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add('A', "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- "k2" + Expect.sequenceEqual original (dict ['A', "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add('A', ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add('B',()) + Expect.sequenceEqual original (dict ['A', (); 'B', ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add('A', 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- 2.0M + Expect.sequenceEqual original (dict ['A', 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add('A', System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- System.IntPtr(2) + Expect.sequenceEqual original (dict ['A', System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add('A', System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.['A'] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict ['A', System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ['A', System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "string keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- false + Expect.sequenceEqual original (dict ["Hi", false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2uy + Expect.sequenceEqual original (dict ["Hi", 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2y + Expect.sequenceEqual original (dict ["Hi", 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2s + Expect.sequenceEqual original (dict ["Hi", 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2us + Expect.sequenceEqual original (dict ["Hi", 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2 + Expect.sequenceEqual original (dict ["Hi", 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2u + Expect.sequenceEqual original (dict ["Hi", 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2L + Expect.sequenceEqual original (dict ["Hi", 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2uL + Expect.sequenceEqual original (dict ["Hi", 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2.0 + Expect.sequenceEqual original (dict ["Hi", 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2.0f + Expect.sequenceEqual original (dict ["Hi", 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 'B' + Expect.sequenceEqual original (dict ["Hi", 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- "k2" + Expect.sequenceEqual original (dict ["Hi", "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add("Bye",()) + Expect.sequenceEqual original (dict ["Hi", (); "Bye", ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- 2.0M + Expect.sequenceEqual original (dict ["Hi", 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- System.IntPtr(2) + Expect.sequenceEqual original (dict ["Hi", System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add("Hi", System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.["Hi"] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict ["Hi", System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict ["Hi", System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] //testList "unit keys" [ - + //not testing this, the concept is ridiculous //] #if !FABLE_COMPILER_PYTHON - //testList "decimal keys" [ - - //] + testList "decimal keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- false + Expect.sequenceEqual original (dict [1.0M, false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2uy + Expect.sequenceEqual original (dict [1.0M, 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2y + Expect.sequenceEqual original (dict [1.0M, 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2s + Expect.sequenceEqual original (dict [1.0M, 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2us + Expect.sequenceEqual original (dict [1.0M, 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2 + Expect.sequenceEqual original (dict [1.0M, 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2u + Expect.sequenceEqual original (dict [1.0M, 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2L + Expect.sequenceEqual original (dict [1.0M, 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2uL + Expect.sequenceEqual original (dict [1.0M, 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2.0 + Expect.sequenceEqual original (dict [1.0M, 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2.0f + Expect.sequenceEqual original (dict [1.0M, 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 'B' + Expect.sequenceEqual original (dict [1.0M, 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- "k2" + Expect.sequenceEqual original (dict [1.0M, "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(2.0M,()) + Expect.sequenceEqual original (dict [1.0M, (); 2.0M, ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- 2.0M + Expect.sequenceEqual original (dict [1.0M, 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [1.0M, System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(1.0M, System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[1.0M] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [1.0M, System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [1.0M, System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] #endif #if !FABLE_COMPILER - //testList "nativeint keys" [ - - //] - //testList "unativeint keys" [ - - //] + testList "nativeint keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- false + Expect.sequenceEqual original (dict [System.IntPtr(1), false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2uy + Expect.sequenceEqual original (dict [System.IntPtr(1), 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2y + Expect.sequenceEqual original (dict [System.IntPtr(1), 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2s + Expect.sequenceEqual original (dict [System.IntPtr(1), 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2us + Expect.sequenceEqual original (dict [System.IntPtr(1), 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2 + Expect.sequenceEqual original (dict [System.IntPtr(1), 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2u + Expect.sequenceEqual original (dict [System.IntPtr(1), 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2L + Expect.sequenceEqual original (dict [System.IntPtr(1), 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2uL + Expect.sequenceEqual original (dict [System.IntPtr(1), 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2.0 + Expect.sequenceEqual original (dict [System.IntPtr(1), 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2.0f + Expect.sequenceEqual original (dict [System.IntPtr(1), 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 'B' + Expect.sequenceEqual original (dict [System.IntPtr(1), 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- "k2" + Expect.sequenceEqual original (dict [System.IntPtr(1), "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(System.IntPtr(2),()) + Expect.sequenceEqual original (dict [System.IntPtr(1), (); System.IntPtr(2), ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- 2.0M + Expect.sequenceEqual original (dict [System.IntPtr(1), 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [System.IntPtr(1), System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(System.IntPtr(1), System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.IntPtr(1)] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [System.IntPtr(1), System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.IntPtr(1), System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] + testList "unativeint keys" [ + testCase "bool values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), true) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- false + Expect.sequenceEqual original (dict [System.UIntPtr(1u), false]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), true]) "Clone should not be affected by original mutation" + testCase "byte values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1uy) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2uy + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2uy]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1uy]) "Clone should not be affected by original mutation" + testCase "sbyte values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1y) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2y + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2y]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1y]) "Clone should not be affected by original mutation" + testCase "int16 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1s) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2s + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2s]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1s]) "Clone should not be affected by original mutation" + testCase "uint16 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1us) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2us + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2us]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1us]) "Clone should not be affected by original mutation" + testCase "int values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2 + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1]) "Clone should not be affected by original mutation" + testCase "uint values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1u) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2u + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2u]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1u]) "Clone should not be affected by original mutation" + testCase "int64 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1L) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2L + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2L]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1L]) "Clone should not be affected by original mutation" + testCase "uint64 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1uL) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2uL + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2uL]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1uL]) "Clone should not be affected by original mutation" + testCase "float values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1.0) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2.0 + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2.0]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1.0]) "Clone should not be affected by original mutation" + testCase "float32 values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1.0f) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2.0f + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2.0f]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1.0f]) "Clone should not be affected by original mutation" + testCase "char values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 'A') + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 'B' + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 'B']) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 'A']) "Clone should not be affected by original mutation" + testCase "string values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), "k1") + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- "k2" + Expect.sequenceEqual original (dict [System.UIntPtr(1u), "k2"]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), "k1"]) "Clone should not be affected by original mutation" + testCase "unit values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), ()) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.Add(System.UIntPtr(2u),()) + Expect.sequenceEqual original (dict [System.UIntPtr(1u), (); System.UIntPtr(2u), ()]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), ()]) "Clone should not be affected by original mutation" + #if !FABLE_COMPILER_PYTHON + testCase "decimal values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), 1.0M) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- 2.0M + Expect.sequenceEqual original (dict [System.UIntPtr(1u), 2.0M]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), 1.0M]) "Clone should not be affected by original mutation" + #endif + #if !FABLE_COMPILER + testCase "nativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), System.IntPtr(1)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- System.IntPtr(2) + Expect.sequenceEqual original (dict [System.UIntPtr(1u), System.IntPtr(2)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), System.IntPtr(1)]) "Clone should not be affected by original mutation" + testCase "unativeint values" <| fun _ -> + let d = new Dictionary() + d.Add(System.UIntPtr(1u), System.UIntPtr(1u)) + let original, copy = constructDeepCopiedObj d + Expect.sequenceEqual copy original "Expected values of copy and original to be equal" + Expect.notReferenceEqual copy original "Expected values of copy and original to be not reference equal" + d.[System.UIntPtr(1u)] <- System.UIntPtr(2u) + Expect.sequenceEqual original (dict [System.UIntPtr(1u), System.UIntPtr(2u)]) "Original schould have been mutated" + Expect.sequenceEqual copy (dict [System.UIntPtr(1u), System.UIntPtr(1u)]) "Clone should not be affected by original mutation" + #endif + ] #endif ] \ No newline at end of file From fd57ba5ef52761e470a045d5ebb2905e55dabc8f Mon Sep 17 00:00:00 2001 From: Kevin Schneider Date: Fri, 24 Jan 2025 15:14:58 +0100 Subject: [PATCH 7/7] implement #44 --- src/DynamicObj/DynObj.fs | 32 +++++++++++++++++- src/DynamicObj/DynamicObj.fs | 64 ++++++++++++++++++++++++++++-------- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/DynamicObj/DynObj.fs b/src/DynamicObj/DynObj.fs index b79ad42..8683d86 100644 --- a/src/DynamicObj/DynObj.fs +++ b/src/DynamicObj/DynObj.fs @@ -216,4 +216,34 @@ module DynObj = /// Prints a formatted string containing all static and dynamic properties of the given DynamicObj /// /// The DynamicObj for which to print a formatted string for - let print (dynObj:DynamicObj) = printfn "%s" (dynObj |> format) \ No newline at end of file + let print (dynObj:DynamicObj) = printfn "%s" (dynObj |> format) + + /// + /// function to deep copy a boxed object (if possible) + /// + /// The following cases are handled (in this precedence): + /// + /// - Basic F# types (bool, byte, sbyte, int16, uint16, int, uint, int64, uint64, nativeint, unativeint, float, float32, char, string, unit, decimal) + /// + /// - ResizeArrays and Dictionaries containing any combination of basic F# types + /// + /// - Dictionaries containing DynamicObj as keys or values in any combination with DynamicObj or basic F# types as keys or values + /// + /// - array<DynamicObj>, list<DynamicObj>, ResizeArray<DynamicObj>: These collections of DynamicObj are copied as a new collection with recursively deep copied elements. + /// + /// - System.ICloneable: If the property implements ICloneable, the Clone() method is called on the property. + /// + /// - DynamicObj (and derived classes): properties that are themselves DynamicObj instances are deep copied recursively. + /// if a derived class has static properties (e.g. instance properties), these will be copied as dynamic properties on the new instance. + /// + /// Note on Classes that inherit from DynamicObj: + /// + /// Classes that inherit from DynamicObj will match the `DynamicObj` typecheck if they do not implement ICloneable. + /// The deep copied instances will be cast to DynamicObj with static/instance properties AND dynamic properties all set as dynamic properties. + /// It should be possible to 'recover' the original type by checking if the needed properties exist as dynamic properties, + /// and then passing them to the class constructor if needed. + /// + /// The object that should be deep copied + /// Whether to include instance properties (= 'static' properties on the class) as dynamic properties on the new instance for matched DynamicObj. + let tryDeepCopyObj (includeInstanceProperties:bool) (o:DynamicObj) = + CopyUtils.tryDeepCopyObj(o, includeInstanceProperties) \ No newline at end of file diff --git a/src/DynamicObj/DynamicObj.fs b/src/DynamicObj/DynamicObj.fs index b0f70a8..ae6be8c 100644 --- a/src/DynamicObj/DynamicObj.fs +++ b/src/DynamicObj/DynamicObj.fs @@ -283,16 +283,21 @@ type DynamicObj() = /// Note on Classes that inherit from DynamicObj: /// /// Classes that inherit from DynamicObj will match the `DynamicObj` typecheck if they do not implement ICloneable. - /// The deep coopied instances will be cast to DynamicObj with static/instance properties AND dynamic properties all set as dynamic properties. + /// The deep copied instances will be cast to DynamicObj with static/instance properties AND dynamic properties all set as dynamic properties. /// It should be possible to 'recover' the original type by checking if the needed properties exist as dynamic properties, /// and then passing them to the class constructor if needed. /// /// The target object to copy dynamic members to - /// Whether existing properties on the target object will be overwritten - member this.DeepCopyPropertiesTo(target:#DynamicObj, ?overWrite) = + /// Whether existing properties on the target object will be overwritten. Default is false + /// Whether to include instance properties (= 'static' properties on the class) as dynamic properties on the new instance. Default is true + member this.DeepCopyPropertiesTo( + target:#DynamicObj, + ?overWrite: bool, + ?includeInstanceProperties:bool + ) = let overWrite = defaultArg overWrite false - - this.GetProperties(true) + let includeInstanceProperties = defaultArg includeInstanceProperties true + this.GetProperties(includeInstanceProperties) |> Seq.iter (fun kv -> match target.TryGetPropertyHelper kv.Key with | Some pi when overWrite -> pi.SetValue target (CopyUtils.tryDeepCopyObj kv.Value) @@ -327,19 +332,20 @@ type DynamicObj() = /// Note on Classes that inherit from DynamicObj: /// /// Classes that inherit from DynamicObj will match the `DynamicObj` typecheck if they do not implement ICloneable. - /// The deep coopied instances will be cast to DynamicObj with static/instance properties AND dynamic properties all set as dynamic properties. + /// The deep copied instances will be cast to DynamicObj with static/instance properties AND dynamic properties all set as dynamic properties. /// It should be possible to 'recover' the original type by checking if the needed properties exist as dynamic properties, /// and then passing them to the class constructor if needed. /// - /// The target object to copy dynamic members to - /// Whether existing properties on the target object will be overwritten - member this.DeepCopyProperties() = CopyUtils.tryDeepCopyObj this + /// Whether to include instance properties (= 'static' properties on the class) as dynamic properties on the new instance. Default is true + member this.DeepCopyProperties(?includeInstanceProperties:bool) = + let includeInstanceProperties = defaultArg includeInstanceProperties true + CopyUtils.tryDeepCopyObj(this, includeInstanceProperties) #if !FABLE_COMPILER // Some necessary overrides for methods inherited from System.Dynamic.DynamicObject() // // Needed mainly for making Newtonsoft.Json Serialization work - override this.TryGetMember(binder:GetMemberBinder,result:obj byref ) = + override this.TryGetMember(binder:GetMemberBinder,result:obj byref) = match this.TryGetPropertyValue binder.Name with | Some value -> result <- value; true | None -> false @@ -396,8 +402,39 @@ type DynamicObj() = and CopyUtils = - /// internal helper function to deep copy a boxed object (if possible) - static member tryDeepCopyObj (o:obj) = + /// + /// function to deep copy a boxed object (if possible) + + /// The following cases are handled (in this precedence): + /// + /// - Basic F# types (bool, byte, sbyte, int16, uint16, int, uint, int64, uint64, nativeint, unativeint, float, float32, char, string, unit, decimal) + /// + /// - ResizeArrays and Dictionaries containing any combination of basic F# types + /// + /// - Dictionaries containing DynamicObj as keys or values in any combination with DynamicObj or basic F# types as keys or values + /// + /// - array<DynamicObj>, list<DynamicObj>, ResizeArray<DynamicObj>: These collections of DynamicObj are copied as a new collection with recursively deep copied elements. + /// + /// - System.ICloneable: If the property implements ICloneable, the Clone() method is called on the property. + /// + /// - DynamicObj (and derived classes): properties that are themselves DynamicObj instances are deep copied recursively. + /// if a derived class has static properties (e.g. instance properties), these will be copied as dynamic properties on the new instance. + /// + /// Note on Classes that inherit from DynamicObj: + /// + /// Classes that inherit from DynamicObj will match the `DynamicObj` typecheck if they do not implement ICloneable. + /// The deep copied instances will be cast to DynamicObj with static/instance properties AND dynamic properties all set as dynamic properties. + /// It should be possible to 'recover' the original type by checking if the needed properties exist as dynamic properties, + /// and then passing them to the class constructor if needed. + /// + /// The object that should be deep copied + /// Whether to include instance properties (= 'static' properties on the class) as dynamic properties on the new instance for matched DynamicObj. Default is true + static member tryDeepCopyObj( + o:obj, + ?includeInstanceProperties:bool + ) = + let includeInstanceProperties = defaultArg includeInstanceProperties true + let rec tryDeepCopyObj (o:obj) = match o with @@ -949,8 +986,7 @@ and CopyUtils = | :? DynamicObj as dyn -> let newDyn = DynamicObj() - // might want to keep instance props as dynamic props on copy - for kv in (dyn.GetProperties(true)) do + for kv in (dyn.GetProperties(includeInstanceProperties)) do newDyn.SetProperty(kv.Key, tryDeepCopyObj kv.Value) box newDyn | _ -> o