gavv / gavv/httpexpect

Migrate Number from float64 to big.Float

Open
#191 27 comments 0 reactions 1 assignee Claimed by @angshumanHalder View on GitHub
feature help wanted important
Dominant language
Go
Stars
2.7k
Forks
241
PR merge metrics
No merged PRs in 30d

Description

Currently, Number always converts its value to float64. In many cases it works well, however float64 can't represent big integer values (larger than 2^62) without precision loss.

Actually, there is no native type that can represent ALL values of int64, uint64, and float64 without loss. However, there is a library type that can do it: big.Float (see https://pkg.go.dev/math/big).

Here are the steps:

* replace underlying value of Number from float64 to big.Float

* by default, use precision that is sufficient to represent all values of int64, uint64, and float64 without loss

* allow user to set higher precision in Config (this may be useful if user wants to parse Number from String that contains bigger integer or float)

* rework canonNumber() to return big.Float instead of float64; it should automatically detect precision and create big.Float from any of these types:

* all native float and integer types
* type definitions for those native types (e.g. `type MyInt int`)
* big.Float and big.Int
* json.Number

* rework NewNumber constructor: it should accept interface{} instead of float64 and use canonNumber() to convert it to big.Float

* rework all Number operations, so that they will operate on big.Float values (one stored in Number, another returned from canonNumber for operation argument)

* rework Number.EqualDelta and Number.NotEqualDelta: they should accept interface{} instead of float64; this will allow user to pass big.Float instead of float64, when necessary

* rework JSON decoding:

* find places where we decode JSON: canonValue, Response, WebsocketMessage; configure JSON decoder to use json.Number instead of float64 (see https://pkg.go.dev/encoding/json#Decoder.UseNumber)

* ensure that canonValue() and other canonization functions does not cause precision loss

* rework Number creation

* Expect.Number() should accept interface{} instead of float64

* rework Value.Number() - it should not force float64 type

* rework String.AsNumber() - it should correctly parse big floats and integers

* find all invocations to newNumber() that have unnecessary casts to float64 and pass integers instead; e.g. `newNumber(a.chain, float64(len(a.value)))` can be now replaced with `newNumber(a.chain, len(a.value))` because Number now supports integers

* adjust equality checks:

* find all places that do deep equality checks (e.g. in Object, Array) using reflect.DeepEqual

* ensure that they will work when original values have different representations for same numbers (e.g. json.Number vs float64 vs big.Float)

* cover these cases with unit tests

* add new getters for Number:

* add 4 new methods: AsInt (returns int64), AsUint (return uint64), AsFloat (return float64), AsBig (return big.Float)

* each method should report failure if underlying value can't be converted to requested types without loss

* add IsBig (similar to other Is methods, see #155)

* mark Number.Raw as deprecated and ask user to use AsFloat instead; in httpexpect v3, when we will be able to break compatibility, we'll undeprecate Raw, but change its return type to big.Float

* adjust DefaultFormatter to handle big.Float values:

* if value is integer, print it as integer

* otherwise print it in non-scientific form (see also #190)

* adjust tests:

* add unit tests for Number to check how it works with big integers and floats

* add unit tests for Value.Number() to check how it works with json.Number and integers that can't be represented without loss as float64

* rework tests for String.AsNumber() - rework float_precision test, add tests for big floats and integers that can't be parsed with default precision, but can be parsed when setting higher precision in Config

* cover big integers and floats, and different precisions, in e2e tests (e.g. in e2e_basic_test.go)

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.