Add tests for folly::dynamic ordering comparison operators on scalar/string...
Add tests for folly::dynamic ordering comparison operators on scalar/string types and highlight some bugs Summary: # Summary Currently nullptr vs nullptr and int vs double ordering comparison operators (e.g. `operator<`) are inconsistent with their equality operators. This diff just adds tests to increase coverage and highlight the broken areas. The subsequent diffs will address the issues individually. The behavior on nulls at least has been present since the very beginning of when a CompareOp was added for it in 2017. More details are below. # Bug 1: nullptr vs nullptr If we have ``` folly::dynamic a(nullptr); folly::dynamic b(nullptr); a < b // returns true a == b // returns true ``` This violates that the two should be equal if `!(a < b) && !(b < a)` given that this expression will return `false`, whereas `a == b` returns `true`. This property is required by e.g. std::sets. If one puts a `folly::dynamic(nullptr)` in an std::set with the current behavior, when iterating it will be found, and will contribute to its size, but `std::set::find()` on it will return false. Hash-based sets are unaffected - given that the hash and `operator==` implementations are correct. The fix is straightforward. `struct dynamic::CompareOp<std::nullptr_t>` in dynamic-inl.h should return false. # Bug 2: int vs double (hash + ordering operators) The `folly::dynamic==` operator does numeric comparison for int64 vs double - whereas the `folly::dynamic<` operator does not - instead falling back on comparing against the Type enum value. Similar to the above this violates the principle of `operator<` being usable for checking equality - given that it is really just checking type equality - but has already been established in the code path that they're different types. Hashing is also inconsistent given that a hash of dynamic(2.0) will not equal dynamic(2) even though they are equal, given that each uses the hash of the underlying type. When ordering is fixed, hashing should be too so that hash based and ordering based containers have the same behavior. The fixes are straightforward. operator< in dynamic.cpp should pull the same logic from operator== with regards int vs double. See https://www.internalfb.com/code/fbsource/[4e70ca24b9ec]/fbcode/folly/dynamic.cpp?lines=97-126 hashing can be resolved by having doubles use integer hashing in dynamic.cpp - https://www.internalfb.com/code/fbsource/[4e70ca24b9ec]/fbcode/folly/dynamic.cpp?lines=307 --- Reviewed By: Gownta Differential Revision: D33465564 fbshipit-source-id: 43b926837e20f4a9afe15ee0032d469864e360c0
Showing
Please register or sign in to comment