Zaid-Ajaj / Fable.Remoting

Type-safe communication layer (RPC-style) for F# featuring Fable and .NET Apps
https://zaid-ajaj.github.io/Fable.Remoting/
MIT License
272 stars 55 forks source link

Update integration tests to use Fable v4.9.0 #358

Closed Zaid-Ajaj closed 6 months ago

Zaid-Ajaj commented 6 months ago

@kerams I've updated the tests to use latest Fable, currently at v4.9.0 but the results aren't very good

Test Results ``` ========== SUMMARY ========== Total test count 216 Passed tests 164 Failed tests 52 Skipped tests 0 ========== TESTS ========== √ Fable.Remoting / Proxy.combineWithBaseUrlWorks √ Fable.Remoting / IServer.simulateLongComputation cancellation √ Fable.Remoting / IServer.getLength √ Fable.Remoting / IServer.echoTupleMap √ Fable.Remoting / IServer.echoTupleSet √ Fable.Remoting / IServer.returnUnit √ Fable.Remoting / IServer.intToUnit √ Fable.Remoting / IServer.tupleToUnit √ Fable.Remoting / IServer.tupleToTuple √ Fable.Remoting / IServer.echoAnonymousRecord √ Fable.Remoting / IServer.echoNestedAnonRecord √ Fable.Remoting / IServer.binaryContent √ Fable.Remoting / IServer.echoTestCommand √ Fable.Remoting / IServer.privateConstructor √ Fable.Remoting / IServer.echoRemoteWorkEntity √ Fable.Remoting / IServer.binaryContent √ Fable.Remoting / IServer.echoToken √ Fable.Remoting / ISever.echoInteger √ Fable.Remoting / IServer.simpleUnit √ Fable.Remoting / IServer.echoString √ Fable.Remoting / IServer.echoRecordWithChar √ Fable.Remoting / IServer.echoRecordWithChar using characters with accents √ Fable.Remoting / IServer.echoUnionOfOtherUnions √ Fable.Remoting / IServer.echoBool √ Fable.Remoting / IServer.mapRecordAsKey √ Fable.Remoting / IServer.mapDateTimeOffsetAsKey √ Fable.Remoting / IServer.echoIntKeyMap √ Fable.Remoting / IServer.echoBigIntKeyMap √ Fable.Remoting / IServer.echoLongKeyMap √ Fable.Remoting / IServer.echoDecimalKeyMap √ Fable.Remoting / IServer.setRecordAsValue √ Fable.Remoting / IServer.echoIntOption √ Fable.Remoting / IServer.echoStringOption √ Fable.Remoting / IServer.echoPrimitiveLong √ Fable.Remoting / IServer.echoPrimitiveLong with large values √ Fable.Remoting / IServer.echoComplexLong √ Fable.Remoting / IServer.echoOptionalLong √ Fable.Remoting / IServer.echoSingleDULong √ Fable.Remoting / IServer.echoLongInGenericUnion √ Fable.Remoting / IServer.echoSimpleUnionType √ Fable.Remoting / IServer.echoGenericUnionInt √ Fable.Remoting / IServer.echoGenericUnionString √ Fable.Remoting / IServer.echoRecord √ Fable.Remoting / IServer.echoHighScores √ Fable.Remoting / IServer.echoHighScores without do √ Fable.Remoting / IServer.echoHighScores √ Fable.Remoting / IServer.echoHighScores without do √ Fable.Remoting / IServer.echoNestedGeneric √ Fable.Remoting / IServer.echoOtherDataC √ Fable.Remoting / IServer.echoIntList √ Fable.Remoting / IServer.echoSingleCase √ Fable.Remoting / IServer.echoStringList √ Fable.Remoting / IServer.echoBoolList √ Fable.Remoting / IServer.echoListOfListsOfStrings √ Fable.Remoting / IServer.echoResult for Result √ Fable.Remoting / IServer.echoMap √ Fable.Remoting / IServer.echoSet √ Fable.Remoting / IServer.echoBigInteger √ Fable.Remoting / IServer.throwError √ Fable.Remoting / IServer.throwBinaryError √ Fable.Remoting / IServer.mutliArgFunc √ Fable.Remoting / IServer.mutliArgFunc partially applied √ Fable.Remoting / IServer.pureAsync √ Fable.Remoting / IServer.asyncNestedGeneric √ Fable.Remoting / IServer.multiArgComplex √ Fable.Remoting / IServer.getSeq √ Fable.Remoting / IServer.echoGenericMap √ Fable.Remoting / IServer.echoRecursiveRecord √ Fable.Remoting / IServer.echoTree (recursive union) √ Fable.Remoting / IServer.multiArgComplex partially applied √ Fable.Remoting / IServer.tuplesAndLists √ Fable.Remoting / IServer.datetime √ Fable.Remoting / IServer.datetimeoffset √ Fable.Remoting / IServer.largeRecursiveRecord √ Fable.Remoting / IServer.echoPosition √ Fable.Remoting / IServer.command √ Fable.Remoting / IServer.echoDateOnlyMap √ Fable.Remoting / IServer.echoTimeOnlyMap √ Fable.Remoting binary / IBinaryServer.getLegth √ Fable.Remoting binary / IBinaryServer.mapDateTimeOffsetAsKey √ Fable.Remoting binary / IBinaryServer.echoRecordWithChar √ Fable.Remoting binary / IBinaryServer.echoIntKeyMap √ Fable.Remoting binary / IBinaryServer.echoBigIntKeyMap √ Fable.Remoting binary / IBinaryServer.echoLongKeyMap √ Fable.Remoting binary / IBinaryServer.echoDecimalKeyMap √ Fable.Remoting binary / IBinaryServer.echoTupleMap √ Fable.Remoting binary / IServer.echoTupleSet √ Fable.Remoting binary / IBinaryServer.returnUnit √ Fable.Remoting binary / IBinaryServer.intToUnit √ Fable.Remoting binary / IBinaryServer.tupleToUnit √ Fable.Remoting binary / IBinaryServer.tupleToTuple √ Fable.Remoting binary / IBinaryServer.echoAnonymousRecord √ Fable.Remoting binary / IBinaryServer.echoNestedAnonRecord √ Fable.Remoting binary / IBinaryServer.binaryContent √ Fable.Remoting binary / IBinaryServer.privateConstructor √ Fable.Remoting binary / IBinaryServer.echoRemoteWorkEntity √ Fable.Remoting binary / IBinaryServer.binaryContentInOut √ Fable.Remoting binary / IBinaryServer.echoInteger √ Fable.Remoting binary / IBinaryServer.simpleUnit √ Fable.Remoting binary / IBinaryServer.echoString √ Fable.Remoting binary / IBinaryServer.echoBool √ Fable.Remoting binary / IBinaryServer.mapRecordAsKey √ Fable.Remoting binary / IServer.setRecordAsValue √ Fable.Remoting binary / IBinaryServer.echoIntOption √ Fable.Remoting binary / IBinaryServer.echoStringOption √ Fable.Remoting binary / IBinaryServer.echoPrimitiveLong √ Fable.Remoting binary / IBinaryServer.echoPrimitiveLong with large values √ Fable.Remoting binary / IBinaryServer.echoComplexLong √ Fable.Remoting binary / IBinaryServer.echoOptionalLong √ Fable.Remoting binary / IBinaryServer.echoSingleDULong √ Fable.Remoting binary / IBinaryServer.echoLongInGenericUnion √ Fable.Remoting binary / IBinaryServer.echoSimpleUnionType √ Fable.Remoting binary / IBinaryServer.echoGenericUnionInt √ Fable.Remoting binary / IBinaryServer.echoGenericUnionString √ Fable.Remoting binary / IBinaryServer.echoRecord √ Fable.Remoting binary / IBinaryServer.echoHighScores √ Fable.Remoting binary / IBinaryServer.echoHighScores without do √ Fable.Remoting binary / IBinaryServer.echoHighScores √ Fable.Remoting binary / IBinaryServer.echoHighScores without do √ Fable.Remoting binary / IBinaryServer.echoNestedGeneric √ Fable.Remoting binary / IBinaryServer.echoOtherDataC √ Fable.Remoting binary / IBinaryServer.echoIntList √ Fable.Remoting binary / IBinaryServer.echoSingleCase √ Fable.Remoting binary / IBinaryServer.echoStringList √ Fable.Remoting binary / IBinaryServer.echoBoolList √ Fable.Remoting binary / IBinaryServer.echoListOfListsOfStrings √ Fable.Remoting binary / IBinaryServer.echoResult for Result √ Fable.Remoting binary / IBinaryServer.echoMap √ Fable.Remoting binary / IServer.echoSet √ Fable.Remoting binary / IBinaryServer.echoBigInteger √ Fable.Remoting binary / IBinaryServer.throwError √ Fable.Remoting binary / IBinaryServer.throwBinaryError √ Fable.Remoting binary / IBinaryServer.mutliArgFunc √ Fable.Remoting binary / IBinaryServer.mutliArgFunc partially applied √ Fable.Remoting binary / IBinaryServer.pureAsync √ Fable.Remoting binary / IBinaryServer.asyncNestedGeneric √ Fable.Remoting binary / IBinaryServer.multiArgComplex √ Fable.Remoting binary / IBinaryServer.echoGenericMap √ Fable.Remoting binary / IBinaryServer.genericDictionary √ Fable.Remoting binary / IBinaryServer.echoRecursiveRecord √ Fable.Remoting binary / IBinaryServer.echoTree (recursive union) √ Fable.Remoting binary / IBinaryServer.multiArgComplex partially applied √ Fable.Remoting binary / IBinaryServer.tuplesAndLists √ Fable.Remoting binary / IBinaryServer.timespans √ Fable.Remoting binary / IBinaryServer.unitOfMeasure √ Fable.Remoting binary / IBinaryServer.enum √ Fable.Remoting binary / IBinaryServer.datetime √ Fable.Remoting binary / IBinaryServer.datetimeoffset √ Fable.Remoting binary / IBinaryServer.guid √ Fable.Remoting binary / IBinaryServer.largeRecursiveRecord √ Fable.Remoting binary / IBinaryServer.echoIntOptionOption √ Fable.Remoting binary / IBinaryServer.echoMaybeBoolList √ Fable.Remoting binary / IBinaryServer.array3tuples √ Fable.Remoting binary / IBinaryServer.echoDateOnlyMap √ Fable.Remoting binary / IBinaryServer.echoTimeOnlyMap √ Fable.Remoting binary / IBinaryServer.pureTask √ Fable.Remoting binary / IBinaryServer.echoMapTask X / IBinaryServer.stringEnum √ Cookie Server / ICookieServer.checkCookie √ Secure API Tests / IAuthServer can be used by resolving access tokens √ Message Pack serialization tests / Dictionary with type as key works √ Message Pack serialization tests / Unit X Message Pack serialization tests / Fixed negative number, single byte X Message Pack serialization tests / Maybe X Message Pack serialization tests / Nested maybe array works X Message Pack serialization tests / Record √ Message Pack serialization tests / None X Message Pack serialization tests / Some string works X Message Pack serialization tests / Long serialized as fixnum X Message Pack serialization tests / Long serialized as int16, 3 bytes X Message Pack serialization tests / uint64, 9 bytes X Message Pack serialization tests / int64, 9 bytes X Message Pack serialization tests / Array of 3 bools, 4 bytes X Message Pack serialization tests / List of fixnums, 5 bytes X Message Pack serialization tests / DateTime X Message Pack serialization tests / DateTime conversions preverses Kind X Message Pack serialization tests / DateTimeOffset X Message Pack serialization tests / String16 with non-ASCII characters X Message Pack serialization tests / Fixstr with non-ASCII characters X Message Pack serialization tests / String32 with non-ASCII characters X Message Pack serialization tests / Negative long X Message Pack serialization tests / Decimal X Message Pack serialization tests / Map16 with map X Message Pack serialization tests / Fixmap with dictionary of nothing X Message Pack serialization tests / Map32 with dictionary X Message Pack serialization tests / Generic map X Message Pack serialization tests / Set16 √ Message Pack serialization tests / Generating large sets works √ Message Pack serialization tests / Comparing large sets works X Message Pack serialization tests / Set32 X Message Pack serialization tests / Recursive set X Message Pack serialization tests / Binary data bin8, 5 bytes X Message Pack serialization tests / Binary data bin16, 303 bytes X Message Pack serialization tests / Binary data bin32, 80005 bytes X Message Pack serialization tests / Array32 of long X Message Pack serialization tests / Array32 of int32 X Message Pack serialization tests / Array32 of uint32 X Message Pack serialization tests / Array of single X Message Pack serialization tests / Array of double X Message Pack serialization tests / Recursive record X Message Pack serialization tests / Complex tuple X Message Pack serialization tests / Bigint X Message Pack serialization tests / TimeSpan X Message Pack serialization tests / Enum X Message Pack serialization tests / Guid X Message Pack serialization tests / Results X Message Pack serialization tests / Units of measure X Message Pack serialization tests / Value option X Message Pack serialization tests / Union cases with no parameters X Message Pack serialization tests / Option of option X Message Pack serialization tests / List of unions X Message Pack serialization tests / Array of 3-tuples X Message Pack serialization tests / Chars X Message Pack serialization tests / Bytes X Message Pack serialization tests / DateOnlyMap X Message Pack serialization tests / TimeOnlyMap ```

It's funny because from the binary server tests only IBinaryServer.stringEnum is failing but then almost all msg pack serialization tests are failing (except for a few).

Any chance you could have a look?

Zaid-Ajaj commented 6 months ago

The IBinaryServer.stringEnum test is failing where the data sent to the server is

["secondString"]

and the response:

{
    "error": "Message: The given key 'secondString' was not present in the dictionary., request body: Some \"[\"secondString\"]\"",
    "ignored": false,
    "handled": true
}
kerams commented 6 months ago

I'll find some time this week.

If I remember right Fable.Remoting binary tests are Client-Server roundtrips where we do deserialization in JS. On the other hand, Message Pack serialization tests probably tests (de)serialization in JS.

Zaid-Ajaj commented 6 months ago

No rush 😄 no one seems to have complained about this yet since most things are working as they should (client-server wise) only the client-side roundtripping is failing

kerams commented 6 months ago

Could IBinaryServer.stringEnum indicate a problem in Fable.SimpleJson on the server?

The write failures are a symptom of a regression in Fable around the (un)currying of function parameters. I see this in 4.5.0, which would incidentally explain why I couldn't get MessagePack to work in Fable.SignalR some time ago.

When I change

let private serializerCache = System.Collections.Generic.Dictionary<string, obj -> ResizeArray<byte> -> unit> ()

(and modify writeObject accordingly) to

let private serializerCache = System.Collections.Generic.Dictionary<string, Action<obj, ResizeArray<byte>>> ()

all Message Pack serialization tests with the exception of Enum start passing.

cc @MangelMaxime

MangelMaxime commented 6 months ago

@kerams I am no expert regarding the curry/uncurry stuff.

You are problem better to open an issue on Fable repo so others can have a look at it. The lines which seems to cause problem is outArg = curry2(v);.

kerams commented 6 months ago

IBinaryServer.stringEnum string enum is failing because the string representation of a DU case is now camel-cased, and so no match is found on the server.

with the exception of Enum start passing

because of native bigint support, writeInt64 (box x :?> int64) had to be changed to writeInt64 (box x :?> int |> int64) - int to int64 conversions are no longer a no-op.

kerams commented 6 months ago

a DU case is now camel-cased

Fable 4 now does this automatically. I suggest we only support StringEnum with CaseRules.None - they are rare in Client-Server communication anyway.

Zaid-Ajaj commented 6 months ago

Fable 4 now does this automatically. I suggest we only support StringEnum with CaseRules.None - they are rare in Client-Server communication anyway.

That sounds reasonable, I tend to think about [<StringEnum>] in Fable intended for interop purposes, not client-server comms

Hm, why is this Fable only? If the server doesn't know it's dealing with a string enum, it will serialize enums as numbers.

I tried to simplify the setup but not having the shared project reference Fable.Core but I see that you managed to work around it 🎉 really appreciate it @kerams ❤️

Zaid-Ajaj commented 6 months ago

Merged and published a batch of packages based on changes to the MsgPack package, should be usable with latest Fable 🚀