12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334 |
- /*
- Copyright 2014 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package resource
- import (
- "encoding/json"
- "math/rand"
- "strings"
- "testing"
- "unicode"
- fuzz "github.com/google/gofuzz"
- "github.com/spf13/pflag"
- inf "gopkg.in/inf.v0"
- )
- var (
- testQuantityFlag = QuantityFlag("quantityFlag", "1M", "dummy flag for testing the quantity flag mechanism")
- )
- var useInfDec bool
- func amount(i int64, exponent int) infDecAmount {
- // See the below test-- scale is the negative of an exponent.
- return infDecAmount{inf.NewDec(i, inf.Scale(-exponent))}
- }
- func dec(i int64, exponent int) infDecAmount {
- // See the below test-- scale is the negative of an exponent.
- return infDecAmount{inf.NewDec(i, inf.Scale(-exponent))}
- }
- func decQuantity(i int64, exponent int, format Format) Quantity {
- return Quantity{d: dec(i, exponent), Format: format}
- }
- func intQuantity(i int64, exponent Scale, format Format) Quantity {
- return Quantity{i: int64Amount{value: i, scale: exponent}, Format: format}
- }
- func TestDec(t *testing.T) {
- table := []struct {
- got infDecAmount
- expect string
- }{
- {dec(1, 0), "1"},
- {dec(1, 1), "10"},
- {dec(5, 2), "500"},
- {dec(8, 3), "8000"},
- {dec(2, 0), "2"},
- {dec(1, -1), "0.1"},
- {dec(3, -2), "0.03"},
- {dec(4, -3), "0.004"},
- }
- for _, item := range table {
- if e, a := item.expect, item.got.Dec.String(); e != a {
- t.Errorf("expected %v, got %v", e, a)
- }
- }
- }
- // TestQuantityParseZero ensures that when a 0 quantity is passed, its string value is 0
- func TestQuantityParseZero(t *testing.T) {
- zero := MustParse("0")
- if expected, actual := "0", zero.String(); expected != actual {
- t.Errorf("Expected %v, actual %v", expected, actual)
- }
- }
- // TestQuantityAddZeroPreservesSuffix verifies that a suffix is preserved
- // independent of the order of operations when adding a zero and non-zero val
- func TestQuantityAddZeroPreservesSuffix(t *testing.T) {
- testValues := []string{"100m", "1Gi"}
- zero := MustParse("0")
- for _, testValue := range testValues {
- value := MustParse(testValue)
- v1 := *value.Copy()
- // ensure non-zero + zero = non-zero (suffix preserved)
- v1.Add(zero)
- // ensure zero + non-zero = non-zero (suffix preserved)
- v2 := *zero.Copy()
- v2.Add(value)
- if v1.String() != testValue {
- t.Errorf("Expected %v, actual %v", testValue, v1.String())
- continue
- }
- if v2.String() != testValue {
- t.Errorf("Expected %v, actual %v", testValue, v2.String())
- }
- }
- }
- // TestQuantitySubZeroPreservesSuffix verifies that a suffix is preserved
- // independent of the order of operations when subtracting a zero and non-zero val
- func TestQuantitySubZeroPreservesSuffix(t *testing.T) {
- testValues := []string{"100m", "1Gi"}
- zero := MustParse("0")
- for _, testValue := range testValues {
- value := MustParse(testValue)
- v1 := *value.Copy()
- // ensure non-zero - zero = non-zero (suffix preserved)
- v1.Sub(zero)
- // ensure we preserved the input value
- if v1.String() != testValue {
- t.Errorf("Expected %v, actual %v", testValue, v1.String())
- }
- // ensure zero - non-zero = -non-zero (suffix preserved)
- v2 := *zero.Copy()
- v2.Sub(value)
- negVal := *value.Copy()
- negVal.Neg()
- if v2.String() != negVal.String() {
- t.Errorf("Expected %v, actual %v", negVal.String(), v2.String())
- }
- }
- }
- // Verifies that you get 0 as canonical value if internal value is 0, and not 0<suffix>
- func TestQuantityCanocicalizeZero(t *testing.T) {
- val := MustParse("1000m")
- val.i.Sub(int64Amount{value: 1})
- zero := Quantity{i: val.i, Format: DecimalSI}
- if expected, actual := "0", zero.String(); expected != actual {
- t.Errorf("Expected %v, actual %v", expected, actual)
- }
- }
- func TestQuantityCmp(t *testing.T) {
- table := []struct {
- x string
- y string
- expect int
- }{
- {"0", "0", 0},
- {"100m", "50m", 1},
- {"50m", "100m", -1},
- {"10000T", "100Gi", 1},
- }
- for _, testCase := range table {
- q1 := MustParse(testCase.x)
- q2 := MustParse(testCase.y)
- if result := q1.Cmp(q2); result != testCase.expect {
- t.Errorf("X: %v, Y: %v, Expected: %v, Actual: %v", testCase.x, testCase.y, testCase.expect, result)
- }
- }
- nils := []struct {
- x *inf.Dec
- y *inf.Dec
- expect int
- }{
- {dec(0, 0).Dec, dec(0, 0).Dec, 0},
- {nil, dec(0, 0).Dec, 0},
- {dec(0, 0).Dec, nil, 0},
- {nil, nil, 0},
- {nil, dec(10, 0).Dec, -1},
- {nil, dec(-10, 0).Dec, 1},
- {dec(10, 0).Dec, nil, 1},
- {dec(-10, 0).Dec, nil, -1},
- }
- for _, nilCase := range nils {
- q1 := Quantity{d: infDecAmount{nilCase.x}, Format: DecimalSI}
- q2 := Quantity{d: infDecAmount{nilCase.y}, Format: DecimalSI}
- if result := q1.Cmp(q2); result != nilCase.expect {
- t.Errorf("X: %v, Y: %v, Expected: %v, Actual: %v", nilCase.x, nilCase.y, nilCase.expect, result)
- }
- }
- }
- func TestParseQuantityString(t *testing.T) {
- table := []struct {
- input string
- positive bool
- value string
- num, denom, suffix string
- }{
- {"0.025Ti", true, "0.025", "0", "025", "Ti"},
- {"1.025Ti", true, "1.025", "1", "025", "Ti"},
- {"-1.025Ti", false, "-1.025", "1", "025", "Ti"},
- {".", true, ".", "0", "", ""},
- {"-.", false, "-.", "0", "", ""},
- {"1E-3", true, "1", "1", "", "E-3"},
- }
- for _, test := range table {
- positive, value, num, denom, suffix, err := parseQuantityString(test.input)
- if err != nil {
- t.Errorf("%s: error: %v", test.input, err)
- continue
- }
- if positive != test.positive || value != test.value || num != test.num || denom != test.denom || suffix != test.suffix {
- t.Errorf("%s: unmatched: %t %q %q %q %q", test.input, positive, value, num, denom, suffix)
- }
- }
- }
- func TestQuantityParse(t *testing.T) {
- if _, err := ParseQuantity(""); err == nil {
- t.Errorf("expected empty string to return error")
- }
- table := []struct {
- input string
- expect Quantity
- }{
- {"0", decQuantity(0, 0, DecimalSI)},
- {"0n", decQuantity(0, 0, DecimalSI)},
- {"0u", decQuantity(0, 0, DecimalSI)},
- {"0m", decQuantity(0, 0, DecimalSI)},
- {"0Ki", decQuantity(0, 0, BinarySI)},
- {"0k", decQuantity(0, 0, DecimalSI)},
- {"0Mi", decQuantity(0, 0, BinarySI)},
- {"0M", decQuantity(0, 0, DecimalSI)},
- {"0Gi", decQuantity(0, 0, BinarySI)},
- {"0G", decQuantity(0, 0, DecimalSI)},
- {"0Ti", decQuantity(0, 0, BinarySI)},
- {"0T", decQuantity(0, 0, DecimalSI)},
- // Quantity less numbers are allowed
- {"1", decQuantity(1, 0, DecimalSI)},
- // Binary suffixes
- {"1Ki", decQuantity(1024, 0, BinarySI)},
- {"8Ki", decQuantity(8*1024, 0, BinarySI)},
- {"7Mi", decQuantity(7*1024*1024, 0, BinarySI)},
- {"6Gi", decQuantity(6*1024*1024*1024, 0, BinarySI)},
- {"5Ti", decQuantity(5*1024*1024*1024*1024, 0, BinarySI)},
- {"4Pi", decQuantity(4*1024*1024*1024*1024*1024, 0, BinarySI)},
- {"3Ei", decQuantity(3*1024*1024*1024*1024*1024*1024, 0, BinarySI)},
- {"10Ti", decQuantity(10*1024*1024*1024*1024, 0, BinarySI)},
- {"100Ti", decQuantity(100*1024*1024*1024*1024, 0, BinarySI)},
- // Decimal suffixes
- {"5n", decQuantity(5, -9, DecimalSI)},
- {"4u", decQuantity(4, -6, DecimalSI)},
- {"3m", decQuantity(3, -3, DecimalSI)},
- {"9", decQuantity(9, 0, DecimalSI)},
- {"8k", decQuantity(8, 3, DecimalSI)},
- {"50k", decQuantity(5, 4, DecimalSI)},
- {"7M", decQuantity(7, 6, DecimalSI)},
- {"6G", decQuantity(6, 9, DecimalSI)},
- {"5T", decQuantity(5, 12, DecimalSI)},
- {"40T", decQuantity(4, 13, DecimalSI)},
- {"300T", decQuantity(3, 14, DecimalSI)},
- {"2P", decQuantity(2, 15, DecimalSI)},
- {"1E", decQuantity(1, 18, DecimalSI)},
- // Decimal exponents
- {"1E-3", decQuantity(1, -3, DecimalExponent)},
- {"1e3", decQuantity(1, 3, DecimalExponent)},
- {"1E6", decQuantity(1, 6, DecimalExponent)},
- {"1e9", decQuantity(1, 9, DecimalExponent)},
- {"1E12", decQuantity(1, 12, DecimalExponent)},
- {"1e15", decQuantity(1, 15, DecimalExponent)},
- {"1E18", decQuantity(1, 18, DecimalExponent)},
- // Nonstandard but still parsable
- {"1e14", decQuantity(1, 14, DecimalExponent)},
- {"1e13", decQuantity(1, 13, DecimalExponent)},
- {"1e3", decQuantity(1, 3, DecimalExponent)},
- {"100.035k", decQuantity(100035, 0, DecimalSI)},
- // Things that look like floating point
- {"0.001", decQuantity(1, -3, DecimalSI)},
- {"0.0005k", decQuantity(5, -1, DecimalSI)},
- {"0.005", decQuantity(5, -3, DecimalSI)},
- {"0.05", decQuantity(5, -2, DecimalSI)},
- {"0.5", decQuantity(5, -1, DecimalSI)},
- {"0.00050k", decQuantity(5, -1, DecimalSI)},
- {"0.00500", decQuantity(5, -3, DecimalSI)},
- {"0.05000", decQuantity(5, -2, DecimalSI)},
- {"0.50000", decQuantity(5, -1, DecimalSI)},
- {"0.5e0", decQuantity(5, -1, DecimalExponent)},
- {"0.5e-1", decQuantity(5, -2, DecimalExponent)},
- {"0.5e-2", decQuantity(5, -3, DecimalExponent)},
- {"0.5e0", decQuantity(5, -1, DecimalExponent)},
- {"10.035M", decQuantity(10035, 3, DecimalSI)},
- {"1.2e3", decQuantity(12, 2, DecimalExponent)},
- {"1.3E+6", decQuantity(13, 5, DecimalExponent)},
- {"1.40e9", decQuantity(14, 8, DecimalExponent)},
- {"1.53E12", decQuantity(153, 10, DecimalExponent)},
- {"1.6e15", decQuantity(16, 14, DecimalExponent)},
- {"1.7E18", decQuantity(17, 17, DecimalExponent)},
- {"9.01", decQuantity(901, -2, DecimalSI)},
- {"8.1k", decQuantity(81, 2, DecimalSI)},
- {"7.123456M", decQuantity(7123456, 0, DecimalSI)},
- {"6.987654321G", decQuantity(6987654321, 0, DecimalSI)},
- {"5.444T", decQuantity(5444, 9, DecimalSI)},
- {"40.1T", decQuantity(401, 11, DecimalSI)},
- {"300.2T", decQuantity(3002, 11, DecimalSI)},
- {"2.5P", decQuantity(25, 14, DecimalSI)},
- {"1.01E", decQuantity(101, 16, DecimalSI)},
- // Things that saturate/round
- {"3.001n", decQuantity(4, -9, DecimalSI)},
- {"1.1E-9", decQuantity(2, -9, DecimalExponent)},
- {"0.0000000001", decQuantity(1, -9, DecimalSI)},
- {"0.0000000005", decQuantity(1, -9, DecimalSI)},
- {"0.00000000050", decQuantity(1, -9, DecimalSI)},
- {"0.5e-9", decQuantity(1, -9, DecimalExponent)},
- {"0.9n", decQuantity(1, -9, DecimalSI)},
- {"0.00000012345", decQuantity(124, -9, DecimalSI)},
- {"0.00000012354", decQuantity(124, -9, DecimalSI)},
- {"9Ei", Quantity{d: maxAllowed, Format: BinarySI}},
- {"9223372036854775807Ki", Quantity{d: maxAllowed, Format: BinarySI}},
- {"12E", decQuantity(12, 18, DecimalSI)},
- // We'll accept fractional binary stuff, too.
- {"100.035Ki", decQuantity(10243584, -2, BinarySI)},
- {"0.5Mi", decQuantity(.5*1024*1024, 0, BinarySI)},
- {"0.05Gi", decQuantity(536870912, -1, BinarySI)},
- {"0.025Ti", decQuantity(274877906944, -1, BinarySI)},
- // Things written by trolls
- {"0.000000000001Ki", decQuantity(2, -9, DecimalSI)}, // rounds up, changes format
- {".001", decQuantity(1, -3, DecimalSI)},
- {".0001k", decQuantity(100, -3, DecimalSI)},
- {"1.", decQuantity(1, 0, DecimalSI)},
- {"1.G", decQuantity(1, 9, DecimalSI)},
- }
- for _, asDec := range []bool{false, true} {
- for _, item := range table {
- got, err := ParseQuantity(item.input)
- if err != nil {
- t.Errorf("%v: unexpected error: %v", item.input, err)
- continue
- }
- if asDec {
- got.AsDec()
- }
- if e, a := item.expect, got; e.Cmp(a) != 0 {
- t.Errorf("%v: expected %v, got %v", item.input, e.String(), a.String())
- }
- if e, a := item.expect.Format, got.Format; e != a {
- t.Errorf("%v: expected %#v, got %#v", item.input, e, a)
- }
- if asDec {
- if i, ok := got.AsInt64(); i != 0 || ok {
- t.Errorf("%v: expected inf.Dec to return false for AsInt64: %d", item.input, i)
- }
- continue
- }
- i, ok := item.expect.AsInt64()
- if !ok {
- continue
- }
- j, ok := got.AsInt64()
- if !ok {
- if got.d.Dec == nil && got.i.scale >= 0 {
- t.Errorf("%v: is an int64Amount, but can't return AsInt64: %v", item.input, got)
- }
- continue
- }
- if i != j {
- t.Errorf("%v: expected equivalent representation as int64: %d %d", item.input, i, j)
- }
- }
- for _, item := range table {
- got, err := ParseQuantity(item.input)
- if err != nil {
- t.Errorf("%v: unexpected error: %v", item.input, err)
- continue
- }
- if asDec {
- got.AsDec()
- }
- // verify that we can decompose the input and get the same result by building up from the base.
- positive, _, num, denom, suffix, err := parseQuantityString(item.input)
- if err != nil {
- t.Errorf("%v: unexpected error: %v", item.input, err)
- continue
- }
- if got.Sign() >= 0 && !positive || got.Sign() < 0 && positive {
- t.Errorf("%v: positive was incorrect: %t", item.input, positive)
- continue
- }
- var value string
- if !positive {
- value = "-"
- }
- value += num
- if len(denom) > 0 {
- value += "." + denom
- }
- value += suffix
- if len(value) == 0 {
- t.Errorf("%v: did not parse correctly, %q %q %q", item.input, num, denom, suffix)
- }
- expected, err := ParseQuantity(value)
- if err != nil {
- t.Errorf("%v: unexpected error for %s: %v", item.input, value, err)
- continue
- }
- if expected.Cmp(got) != 0 {
- t.Errorf("%v: not the same as %s", item.input, value)
- continue
- }
- }
- // Try the negative version of everything
- desired := &inf.Dec{}
- expect := Quantity{d: infDecAmount{Dec: desired}}
- for _, item := range table {
- got, err := ParseQuantity("-" + strings.TrimLeftFunc(item.input, unicode.IsSpace))
- if err != nil {
- t.Errorf("-%v: unexpected error: %v", item.input, err)
- continue
- }
- if asDec {
- got.AsDec()
- }
- expected := item.expect
- desired.Neg(expected.AsDec())
- if e, a := expect, got; e.Cmp(a) != 0 {
- t.Errorf("%v: expected %s, got %s", item.input, e.String(), a.String())
- }
- if e, a := expected.Format, got.Format; e != a {
- t.Errorf("%v: expected %#v, got %#v", item.input, e, a)
- }
- }
- // Try everything with an explicit +
- for _, item := range table {
- got, err := ParseQuantity("+" + strings.TrimLeftFunc(item.input, unicode.IsSpace))
- if err != nil {
- t.Errorf("-%v: unexpected error: %v", item.input, err)
- continue
- }
- if asDec {
- got.AsDec()
- }
- if e, a := item.expect, got; e.Cmp(a) != 0 {
- t.Errorf("%v(%t): expected %s, got %s", item.input, asDec, e.String(), a.String())
- }
- if e, a := item.expect.Format, got.Format; e != a {
- t.Errorf("%v: expected %#v, got %#v", item.input, e, a)
- }
- }
- }
- invalid := []string{
- "1.1.M",
- "1+1.0M",
- "0.1mi",
- "0.1am",
- "aoeu",
- ".5i",
- "1i",
- "-3.01i",
- "-3.01e-",
- // trailing whitespace is forbidden
- " 1",
- "1 ",
- }
- for _, item := range invalid {
- _, err := ParseQuantity(item)
- if err == nil {
- t.Errorf("%v parsed unexpectedly", item)
- }
- }
- }
- func TestQuantityRoundUp(t *testing.T) {
- table := []struct {
- in string
- scale Scale
- expect Quantity
- ok bool
- }{
- {"9.01", -3, decQuantity(901, -2, DecimalSI), true},
- {"9.01", -2, decQuantity(901, -2, DecimalSI), true},
- {"9.01", -1, decQuantity(91, -1, DecimalSI), false},
- {"9.01", 0, decQuantity(10, 0, DecimalSI), false},
- {"9.01", 1, decQuantity(10, 0, DecimalSI), false},
- {"9.01", 2, decQuantity(100, 0, DecimalSI), false},
- {"-9.01", -3, decQuantity(-901, -2, DecimalSI), true},
- {"-9.01", -2, decQuantity(-901, -2, DecimalSI), true},
- {"-9.01", -1, decQuantity(-91, -1, DecimalSI), false},
- {"-9.01", 0, decQuantity(-10, 0, DecimalSI), false},
- {"-9.01", 1, decQuantity(-10, 0, DecimalSI), false},
- {"-9.01", 2, decQuantity(-100, 0, DecimalSI), false},
- }
- for _, asDec := range []bool{false, true} {
- for _, item := range table {
- got, err := ParseQuantity(item.in)
- if err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- expect := *item.expect.Copy()
- if asDec {
- got.AsDec()
- }
- if ok := got.RoundUp(item.scale); ok != item.ok {
- t.Errorf("%s(%d,%t): unexpected ok: %t", item.in, item.scale, asDec, ok)
- }
- if got.Cmp(expect) != 0 {
- t.Errorf("%s(%d,%t): unexpected round: %s vs %s", item.in, item.scale, asDec, got.String(), expect.String())
- }
- }
- }
- }
- func TestQuantityCmpInt64AndDec(t *testing.T) {
- table := []struct {
- a, b Quantity
- cmp int
- }{
- {intQuantity(901, -2, DecimalSI), intQuantity(901, -2, DecimalSI), 0},
- {intQuantity(90, -1, DecimalSI), intQuantity(901, -2, DecimalSI), -1},
- {intQuantity(901, -2, DecimalSI), intQuantity(900, -2, DecimalSI), 1},
- {intQuantity(0, 0, DecimalSI), intQuantity(0, 0, DecimalSI), 0},
- {intQuantity(0, 1, DecimalSI), intQuantity(0, -1, DecimalSI), 0},
- {intQuantity(0, -1, DecimalSI), intQuantity(0, 1, DecimalSI), 0},
- {intQuantity(800, -3, DecimalSI), intQuantity(1, 0, DecimalSI), -1},
- {intQuantity(800, -3, DecimalSI), intQuantity(79, -2, DecimalSI), 1},
- {intQuantity(mostPositive, 0, DecimalSI), intQuantity(1, -1, DecimalSI), 1},
- {intQuantity(mostPositive, 1, DecimalSI), intQuantity(1, 0, DecimalSI), 1},
- {intQuantity(mostPositive, 1, DecimalSI), intQuantity(1, 1, DecimalSI), 1},
- {intQuantity(mostPositive, 1, DecimalSI), intQuantity(0, 1, DecimalSI), 1},
- {intQuantity(mostPositive, -16, DecimalSI), intQuantity(1, 3, DecimalSI), -1},
- {intQuantity(mostNegative, 0, DecimalSI), intQuantity(0, 0, DecimalSI), -1},
- {intQuantity(mostNegative, -18, DecimalSI), intQuantity(-1, 0, DecimalSI), -1},
- {intQuantity(mostNegative, -19, DecimalSI), intQuantity(-1, 0, DecimalSI), 1},
- {intQuantity(1*1000000*1000000*1000000, -17, DecimalSI), intQuantity(1, 1, DecimalSI), 0},
- {intQuantity(1*1000000*1000000*1000000, -17, DecimalSI), intQuantity(-10, 0, DecimalSI), 1},
- {intQuantity(-1*1000000*1000000*1000000, -17, DecimalSI), intQuantity(-10, 0, DecimalSI), 0},
- {intQuantity(1*1000000*1000000*1000000, -17, DecimalSI), intQuantity(1, 0, DecimalSI), 1},
- {intQuantity(1*1000000*1000000*1000000+1, -17, DecimalSI), intQuantity(1, 1, DecimalSI), 1},
- {intQuantity(1*1000000*1000000*1000000-1, -17, DecimalSI), intQuantity(1, 1, DecimalSI), -1},
- }
- for _, item := range table {
- if cmp := item.a.Cmp(item.b); cmp != item.cmp {
- t.Errorf("%#v: unexpected Cmp: %d", item, cmp)
- }
- if cmp := item.b.Cmp(item.a); cmp != -item.cmp {
- t.Errorf("%#v: unexpected inverted Cmp: %d", item, cmp)
- }
- }
- for _, item := range table {
- a, b := *item.a.Copy(), *item.b.Copy()
- a.AsDec()
- if cmp := a.Cmp(b); cmp != item.cmp {
- t.Errorf("%#v: unexpected Cmp: %d", item, cmp)
- }
- if cmp := b.Cmp(a); cmp != -item.cmp {
- t.Errorf("%#v: unexpected inverted Cmp: %d", item, cmp)
- }
- }
- for _, item := range table {
- a, b := *item.a.Copy(), *item.b.Copy()
- b.AsDec()
- if cmp := a.Cmp(b); cmp != item.cmp {
- t.Errorf("%#v: unexpected Cmp: %d", item, cmp)
- }
- if cmp := b.Cmp(a); cmp != -item.cmp {
- t.Errorf("%#v: unexpected inverted Cmp: %d", item, cmp)
- }
- }
- for _, item := range table {
- a, b := *item.a.Copy(), *item.b.Copy()
- a.AsDec()
- b.AsDec()
- if cmp := a.Cmp(b); cmp != item.cmp {
- t.Errorf("%#v: unexpected Cmp: %d", item, cmp)
- }
- if cmp := b.Cmp(a); cmp != -item.cmp {
- t.Errorf("%#v: unexpected inverted Cmp: %d", item, cmp)
- }
- }
- }
- func TestQuantityNeg(t *testing.T) {
- table := []struct {
- a Quantity
- out string
- }{
- {intQuantity(901, -2, DecimalSI), "-9010m"},
- {decQuantity(901, -2, DecimalSI), "-9010m"},
- }
- for i, item := range table {
- out := *item.a.Copy()
- out.Neg()
- if out.Cmp(item.a) == 0 {
- t.Errorf("%d: negating an item should not mutate the source: %s", i, out.String())
- }
- if out.String() != item.out {
- t.Errorf("%d: negating did not equal exact value: %s", i, out.String())
- }
- }
- }
- func TestQuantityString(t *testing.T) {
- table := []struct {
- in Quantity
- expect string
- alternate string
- }{
- {decQuantity(1024*1024*1024, 0, BinarySI), "1Gi", "1024Mi"},
- {decQuantity(300*1024*1024, 0, BinarySI), "300Mi", "307200Ki"},
- {decQuantity(6*1024, 0, BinarySI), "6Ki", ""},
- {decQuantity(1001*1024*1024*1024, 0, BinarySI), "1001Gi", "1025024Mi"},
- {decQuantity(1024*1024*1024*1024, 0, BinarySI), "1Ti", "1024Gi"},
- {decQuantity(5, 0, BinarySI), "5", "5000m"},
- {decQuantity(500, -3, BinarySI), "500m", "0.5"},
- {decQuantity(1, 9, DecimalSI), "1G", "1000M"},
- {decQuantity(1000, 6, DecimalSI), "1G", "0.001T"},
- {decQuantity(1000000, 3, DecimalSI), "1G", ""},
- {decQuantity(1000000000, 0, DecimalSI), "1G", ""},
- {decQuantity(1, -3, DecimalSI), "1m", "1000u"},
- {decQuantity(80, -3, DecimalSI), "80m", ""},
- {decQuantity(1080, -3, DecimalSI), "1080m", "1.08"},
- {decQuantity(108, -2, DecimalSI), "1080m", "1080000000n"},
- {decQuantity(10800, -4, DecimalSI), "1080m", ""},
- {decQuantity(300, 6, DecimalSI), "300M", ""},
- {decQuantity(1, 12, DecimalSI), "1T", ""},
- {decQuantity(1234567, 6, DecimalSI), "1234567M", ""},
- {decQuantity(1234567, -3, BinarySI), "1234567m", ""},
- {decQuantity(3, 3, DecimalSI), "3k", ""},
- {decQuantity(1025, 0, BinarySI), "1025", ""},
- {decQuantity(0, 0, DecimalSI), "0", ""},
- {decQuantity(0, 0, BinarySI), "0", ""},
- {decQuantity(1, 9, DecimalExponent), "1e9", ".001e12"},
- {decQuantity(1, -3, DecimalExponent), "1e-3", "0.001e0"},
- {decQuantity(1, -9, DecimalExponent), "1e-9", "1000e-12"},
- {decQuantity(80, -3, DecimalExponent), "80e-3", ""},
- {decQuantity(300, 6, DecimalExponent), "300e6", ""},
- {decQuantity(1, 12, DecimalExponent), "1e12", ""},
- {decQuantity(1, 3, DecimalExponent), "1e3", ""},
- {decQuantity(3, 3, DecimalExponent), "3e3", ""},
- {decQuantity(3, 3, DecimalSI), "3k", ""},
- {decQuantity(0, 0, DecimalExponent), "0", "00"},
- {decQuantity(1, -9, DecimalSI), "1n", ""},
- {decQuantity(80, -9, DecimalSI), "80n", ""},
- {decQuantity(1080, -9, DecimalSI), "1080n", ""},
- {decQuantity(108, -8, DecimalSI), "1080n", ""},
- {decQuantity(10800, -10, DecimalSI), "1080n", ""},
- {decQuantity(1, -6, DecimalSI), "1u", ""},
- {decQuantity(80, -6, DecimalSI), "80u", ""},
- {decQuantity(1080, -6, DecimalSI), "1080u", ""},
- }
- for _, item := range table {
- got := item.in.String()
- if e, a := item.expect, got; e != a {
- t.Errorf("%#v: expected %v, got %v", item.in, e, a)
- }
- q, err := ParseQuantity(item.expect)
- if err != nil {
- t.Errorf("%#v: unexpected error: %v", item.expect, err)
- }
- if len(q.s) == 0 || q.s != item.expect {
- t.Errorf("%#v: did not copy canonical string on parse: %s", item.expect, q.s)
- }
- if len(item.alternate) == 0 {
- continue
- }
- q, err = ParseQuantity(item.alternate)
- if err != nil {
- t.Errorf("%#v: unexpected error: %v", item.expect, err)
- continue
- }
- if len(q.s) != 0 {
- t.Errorf("%#v: unexpected nested string: %v", item.expect, q.s)
- }
- if q.String() != item.expect {
- t.Errorf("%#v: unexpected alternate canonical: %v", item.expect, q.String())
- }
- if len(q.s) == 0 || q.s != item.expect {
- t.Errorf("%#v: did not set canonical string on ToString: %s", item.expect, q.s)
- }
- }
- desired := &inf.Dec{} // Avoid modifying the values in the table.
- for _, item := range table {
- if item.in.Cmp(Quantity{}) == 0 {
- // Don't expect it to print "-0" ever
- continue
- }
- q := item.in
- q.d = infDecAmount{desired.Neg(q.AsDec())}
- if e, a := "-"+item.expect, q.String(); e != a {
- t.Errorf("%#v: expected %v, got %v", item.in, e, a)
- }
- }
- }
- func TestQuantityParseEmit(t *testing.T) {
- table := []struct {
- in string
- expect string
- }{
- {"1Ki", "1Ki"},
- {"1Mi", "1Mi"},
- {"1Gi", "1Gi"},
- {"1024Mi", "1Gi"},
- {"1000M", "1G"},
- {".001Ki", "1024m"},
- {".000001Ki", "1024u"},
- {".000000001Ki", "1024n"},
- {".000000000001Ki", "2n"},
- }
- for _, item := range table {
- q, err := ParseQuantity(item.in)
- if err != nil {
- t.Errorf("Couldn't parse %v", item.in)
- continue
- }
- if e, a := item.expect, q.String(); e != a {
- t.Errorf("%#v: expected %v, got %v", item.in, e, a)
- }
- }
- for _, item := range table {
- q, err := ParseQuantity("-" + item.in)
- if err != nil {
- t.Errorf("Couldn't parse %v", item.in)
- continue
- }
- if q.Cmp(Quantity{}) == 0 {
- continue
- }
- if e, a := "-"+item.expect, q.String(); e != a {
- t.Errorf("%#v: expected %v, got %v (%#v)", item.in, e, a, q.i)
- }
- }
- }
- var fuzzer = fuzz.New().Funcs(
- func(q *Quantity, c fuzz.Continue) {
- q.i = Zero
- if c.RandBool() {
- q.Format = BinarySI
- if c.RandBool() {
- dec := &inf.Dec{}
- q.d = infDecAmount{Dec: dec}
- dec.SetScale(0)
- dec.SetUnscaled(c.Int63())
- return
- }
- // Be sure to test cases like 1Mi
- dec := &inf.Dec{}
- q.d = infDecAmount{Dec: dec}
- dec.SetScale(0)
- dec.SetUnscaled(c.Int63n(1024) << uint(10*c.Intn(5)))
- return
- }
- if c.RandBool() {
- q.Format = DecimalSI
- } else {
- q.Format = DecimalExponent
- }
- if c.RandBool() {
- dec := &inf.Dec{}
- q.d = infDecAmount{Dec: dec}
- dec.SetScale(inf.Scale(c.Intn(4)))
- dec.SetUnscaled(c.Int63())
- return
- }
- // Be sure to test cases like 1M
- dec := &inf.Dec{}
- q.d = infDecAmount{Dec: dec}
- dec.SetScale(inf.Scale(3 - c.Intn(15)))
- dec.SetUnscaled(c.Int63n(1000))
- },
- )
- func TestJSON(t *testing.T) {
- for i := 0; i < 500; i++ {
- q := &Quantity{}
- fuzzer.Fuzz(q)
- b, err := json.Marshal(q)
- if err != nil {
- t.Errorf("error encoding %v: %v", q, err)
- continue
- }
- q2 := &Quantity{}
- err = json.Unmarshal(b, q2)
- if err != nil {
- t.Logf("%d: %s", i, string(b))
- t.Errorf("%v: error decoding %v: %v", q, string(b), err)
- }
- if q2.Cmp(*q) != 0 {
- t.Errorf("Expected equal: %v, %v (json was '%v')", q, q2, string(b))
- }
- }
- }
- func TestJSONWhitespace(t *testing.T) {
- q := Quantity{}
- testCases := []struct {
- in string
- expect string
- }{
- {`" 1"`, "1"},
- {`"1 "`, "1"},
- {`1`, "1"},
- {` 1`, "1"},
- {`1 `, "1"},
- {`10`, "10"},
- {`-1`, "-1"},
- {` -1`, "-1"},
- }
- for _, test := range testCases {
- if err := json.Unmarshal([]byte(test.in), &q); err != nil {
- t.Errorf("%q: %v", test.in, err)
- }
- if q.String() != test.expect {
- t.Errorf("unexpected string: %q", q.String())
- }
- }
- }
- func TestMilliNewSet(t *testing.T) {
- table := []struct {
- value int64
- format Format
- expect string
- exact bool
- }{
- {1, DecimalSI, "1m", true},
- {1000, DecimalSI, "1", true},
- {1234000, DecimalSI, "1234", true},
- {1024, BinarySI, "1024m", false}, // Format changes
- {1000000, "invalidFormatDefaultsToExponent", "1e3", true},
- {1024 * 1024, BinarySI, "1048576m", false}, // Format changes
- }
- for _, item := range table {
- q := NewMilliQuantity(item.value, item.format)
- if e, a := item.expect, q.String(); e != a {
- t.Errorf("Expected %v, got %v; %#v", e, a, q)
- }
- if !item.exact {
- continue
- }
- q2, err := ParseQuantity(q.String())
- if err != nil {
- t.Errorf("Round trip failed on %v", q)
- }
- if e, a := item.value, q2.MilliValue(); e != a {
- t.Errorf("Expected %v, got %v", e, a)
- }
- }
- for _, item := range table {
- q := NewQuantity(0, item.format)
- q.SetMilli(item.value)
- if e, a := item.expect, q.String(); e != a {
- t.Errorf("Set: Expected %v, got %v; %#v", e, a, q)
- }
- }
- }
- func TestNewSet(t *testing.T) {
- table := []struct {
- value int64
- format Format
- expect string
- }{
- {1, DecimalSI, "1"},
- {1000, DecimalSI, "1k"},
- {1234000, DecimalSI, "1234k"},
- {1024, BinarySI, "1Ki"},
- {1000000, "invalidFormatDefaultsToExponent", "1e6"},
- {1024 * 1024, BinarySI, "1Mi"},
- }
- for _, asDec := range []bool{false, true} {
- for _, item := range table {
- q := NewQuantity(item.value, item.format)
- if asDec {
- q.ToDec()
- }
- if e, a := item.expect, q.String(); e != a {
- t.Errorf("Expected %v, got %v; %#v", e, a, q)
- }
- q2, err := ParseQuantity(q.String())
- if err != nil {
- t.Errorf("Round trip failed on %v", q)
- }
- if e, a := item.value, q2.Value(); e != a {
- t.Errorf("Expected %v, got %v", e, a)
- }
- }
- for _, item := range table {
- q := NewQuantity(0, item.format)
- q.Set(item.value)
- if asDec {
- q.ToDec()
- }
- if e, a := item.expect, q.String(); e != a {
- t.Errorf("Set: Expected %v, got %v; %#v", e, a, q)
- }
- }
- }
- }
- func TestNewScaledSet(t *testing.T) {
- table := []struct {
- value int64
- scale Scale
- expect string
- }{
- {1, Nano, "1n"},
- {1000, Nano, "1u"},
- {1, Micro, "1u"},
- {1000, Micro, "1m"},
- {1, Milli, "1m"},
- {1000, Milli, "1"},
- {1, 0, "1"},
- {0, Nano, "0"},
- {0, Micro, "0"},
- {0, Milli, "0"},
- {0, 0, "0"},
- }
- for _, item := range table {
- q := NewScaledQuantity(item.value, item.scale)
- if e, a := item.expect, q.String(); e != a {
- t.Errorf("Expected %v, got %v; %#v", e, a, q)
- }
- q2, err := ParseQuantity(q.String())
- if err != nil {
- t.Errorf("Round trip failed on %v", q)
- }
- if e, a := item.value, q2.ScaledValue(item.scale); e != a {
- t.Errorf("Expected %v, got %v", e, a)
- }
- q3 := NewQuantity(0, DecimalSI)
- q3.SetScaled(item.value, item.scale)
- if q.Cmp(*q3) != 0 {
- t.Errorf("Expected %v and %v to be equal", q, q3)
- }
- }
- }
- func TestScaledValue(t *testing.T) {
- table := []struct {
- fromScale Scale
- toScale Scale
- expected int64
- }{
- {Nano, Nano, 1},
- {Nano, Micro, 1},
- {Nano, Milli, 1},
- {Nano, 0, 1},
- {Micro, Nano, 1000},
- {Micro, Micro, 1},
- {Micro, Milli, 1},
- {Micro, 0, 1},
- {Milli, Nano, 1000 * 1000},
- {Milli, Micro, 1000},
- {Milli, Milli, 1},
- {Milli, 0, 1},
- {0, Nano, 1000 * 1000 * 1000},
- {0, Micro, 1000 * 1000},
- {0, Milli, 1000},
- {0, 0, 1},
- }
- for _, item := range table {
- q := NewScaledQuantity(1, item.fromScale)
- if e, a := item.expected, q.ScaledValue(item.toScale); e != a {
- t.Errorf("%v to %v: Expected %v, got %v", item.fromScale, item.toScale, e, a)
- }
- }
- }
- func TestUninitializedNoCrash(t *testing.T) {
- var q Quantity
- q.Value()
- q.MilliValue()
- q.Copy()
- _ = q.String()
- q.MarshalJSON()
- }
- func TestCopy(t *testing.T) {
- q := NewQuantity(5, DecimalSI)
- c := q.Copy()
- c.Set(6)
- if q.Value() == 6 {
- t.Errorf("Copy didn't")
- }
- }
- func TestQFlagSet(t *testing.T) {
- qf := qFlag{&Quantity{}}
- qf.Set("1Ki")
- if e, a := "1Ki", qf.String(); e != a {
- t.Errorf("Unexpected result %v != %v", e, a)
- }
- }
- func TestQFlagIsPFlag(t *testing.T) {
- var pfv pflag.Value = qFlag{}
- if e, a := "quantity", pfv.Type(); e != a {
- t.Errorf("Unexpected result %v != %v", e, a)
- }
- }
- func TestSub(t *testing.T) {
- tests := []struct {
- a Quantity
- b Quantity
- expected Quantity
- }{
- {decQuantity(10, 0, DecimalSI), decQuantity(1, 1, DecimalSI), decQuantity(0, 0, DecimalSI)},
- {decQuantity(10, 0, DecimalSI), decQuantity(1, 0, BinarySI), decQuantity(9, 0, DecimalSI)},
- {decQuantity(10, 0, BinarySI), decQuantity(1, 0, DecimalSI), decQuantity(9, 0, BinarySI)},
- {Quantity{Format: DecimalSI}, decQuantity(50, 0, DecimalSI), decQuantity(-50, 0, DecimalSI)},
- {decQuantity(50, 0, DecimalSI), Quantity{Format: DecimalSI}, decQuantity(50, 0, DecimalSI)},
- {Quantity{Format: DecimalSI}, Quantity{Format: DecimalSI}, decQuantity(0, 0, DecimalSI)},
- }
- for i, test := range tests {
- test.a.Sub(test.b)
- if test.a.Cmp(test.expected) != 0 {
- t.Errorf("[%d] Expected %q, got %q", i, test.expected.String(), test.a.String())
- }
- }
- }
- func TestNeg(t *testing.T) {
- tests := []struct {
- a Quantity
- b Quantity
- expected Quantity
- }{
- {a: intQuantity(0, 0, DecimalSI), expected: intQuantity(0, 0, DecimalSI)},
- {a: Quantity{}, expected: Quantity{}},
- {a: intQuantity(10, 0, BinarySI), expected: intQuantity(-10, 0, BinarySI)},
- {a: intQuantity(-10, 0, BinarySI), expected: intQuantity(10, 0, BinarySI)},
- {a: decQuantity(0, 0, DecimalSI), expected: intQuantity(0, 0, DecimalSI)},
- {a: decQuantity(10, 0, BinarySI), expected: intQuantity(-10, 0, BinarySI)},
- {a: decQuantity(-10, 0, BinarySI), expected: intQuantity(10, 0, BinarySI)},
- }
- for i, test := range tests {
- a := test.a.Copy()
- a.Neg()
- // ensure value is same
- if a.Cmp(test.expected) != 0 {
- t.Errorf("[%d] Expected %q, got %q", i, test.expected.String(), a.String())
- }
- }
- }
- func TestAdd(t *testing.T) {
- tests := []struct {
- a Quantity
- b Quantity
- expected Quantity
- }{
- {decQuantity(10, 0, DecimalSI), decQuantity(1, 1, DecimalSI), decQuantity(20, 0, DecimalSI)},
- {decQuantity(10, 0, DecimalSI), decQuantity(1, 0, BinarySI), decQuantity(11, 0, DecimalSI)},
- {decQuantity(10, 0, BinarySI), decQuantity(1, 0, DecimalSI), decQuantity(11, 0, BinarySI)},
- {Quantity{Format: DecimalSI}, decQuantity(50, 0, DecimalSI), decQuantity(50, 0, DecimalSI)},
- {decQuantity(50, 0, DecimalSI), Quantity{Format: DecimalSI}, decQuantity(50, 0, DecimalSI)},
- {Quantity{Format: DecimalSI}, Quantity{Format: DecimalSI}, decQuantity(0, 0, DecimalSI)},
- }
- for i, test := range tests {
- test.a.Add(test.b)
- if test.a.Cmp(test.expected) != 0 {
- t.Errorf("[%d] Expected %q, got %q", i, test.expected.String(), test.a.String())
- }
- }
- }
- func TestAddSubRoundTrip(t *testing.T) {
- for k := -10; k <= 10; k++ {
- q := Quantity{Format: DecimalSI}
- var order []int64
- for i := 0; i < 100; i++ {
- j := rand.Int63()
- order = append(order, j)
- q.Add(*NewScaledQuantity(j, Scale(k)))
- }
- for _, j := range order {
- q.Sub(*NewScaledQuantity(j, Scale(k)))
- }
- if !q.IsZero() {
- t.Errorf("addition and subtraction did not cancel: %s", &q)
- }
- }
- }
- func TestAddSubRoundTripAcrossScales(t *testing.T) {
- q := Quantity{Format: DecimalSI}
- var order []int64
- for i := 0; i < 100; i++ {
- j := rand.Int63()
- order = append(order, j)
- q.Add(*NewScaledQuantity(j, Scale(j%20-10)))
- }
- for _, j := range order {
- q.Sub(*NewScaledQuantity(j, Scale(j%20-10)))
- }
- if !q.IsZero() {
- t.Errorf("addition and subtraction did not cancel: %s", &q)
- }
- }
- func TestNegateRoundTrip(t *testing.T) {
- for _, asDec := range []bool{false, true} {
- for k := -10; k <= 10; k++ {
- for i := 0; i < 100; i++ {
- j := rand.Int63()
- q := *NewScaledQuantity(j, Scale(k))
- if asDec {
- q.AsDec()
- }
- b := q.Copy()
- b.Neg()
- b.Neg()
- if b.Cmp(q) != 0 {
- t.Errorf("double negation did not cancel: %s", &q)
- }
- }
- }
- }
- }
- func benchmarkQuantities() []Quantity {
- return []Quantity{
- intQuantity(1024*1024*1024, 0, BinarySI),
- intQuantity(1024*1024*1024*1024, 0, BinarySI),
- intQuantity(1000000, 3, DecimalSI),
- intQuantity(1000000000, 0, DecimalSI),
- intQuantity(1, -3, DecimalSI),
- intQuantity(80, -3, DecimalSI),
- intQuantity(1080, -3, DecimalSI),
- intQuantity(0, 0, BinarySI),
- intQuantity(1, 9, DecimalExponent),
- intQuantity(1, -9, DecimalSI),
- intQuantity(1000000, 10, DecimalSI),
- }
- }
- func BenchmarkQuantityString(b *testing.B) {
- values := benchmarkQuantities()
- b.ResetTimer()
- var s string
- for i := 0; i < b.N; i++ {
- q := values[i%len(values)]
- q.s = ""
- s = q.String()
- }
- b.StopTimer()
- if len(s) == 0 {
- b.Fatal(s)
- }
- }
- func BenchmarkQuantityStringPrecalc(b *testing.B) {
- values := benchmarkQuantities()
- for i := range values {
- _ = values[i].String()
- }
- b.ResetTimer()
- var s string
- for i := 0; i < b.N; i++ {
- q := values[i%len(values)]
- s = q.String()
- }
- b.StopTimer()
- if len(s) == 0 {
- b.Fatal(s)
- }
- }
- func BenchmarkQuantityStringBinarySI(b *testing.B) {
- values := benchmarkQuantities()
- for i := range values {
- values[i].Format = BinarySI
- }
- b.ResetTimer()
- var s string
- for i := 0; i < b.N; i++ {
- q := values[i%len(values)]
- q.s = ""
- s = q.String()
- }
- b.StopTimer()
- if len(s) == 0 {
- b.Fatal(s)
- }
- }
- func BenchmarkQuantityMarshalJSON(b *testing.B) {
- values := benchmarkQuantities()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- q := values[i%len(values)]
- q.s = ""
- if _, err := q.MarshalJSON(); err != nil {
- b.Fatal(err)
- }
- }
- b.StopTimer()
- }
- func BenchmarkQuantityUnmarshalJSON(b *testing.B) {
- values := benchmarkQuantities()
- var json [][]byte
- for _, v := range values {
- data, _ := v.MarshalJSON()
- json = append(json, data)
- }
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- var q Quantity
- if err := q.UnmarshalJSON(json[i%len(values)]); err != nil {
- b.Fatal(err)
- }
- }
- b.StopTimer()
- }
- func BenchmarkParseQuantity(b *testing.B) {
- values := benchmarkQuantities()
- var strings []string
- for _, v := range values {
- strings = append(strings, v.String())
- }
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if _, err := ParseQuantity(strings[i%len(values)]); err != nil {
- b.Fatal(err)
- }
- }
- b.StopTimer()
- }
- func BenchmarkCanonicalize(b *testing.B) {
- values := benchmarkQuantities()
- b.ResetTimer()
- buffer := make([]byte, 0, 100)
- for i := 0; i < b.N; i++ {
- s, _ := values[i%len(values)].CanonicalizeBytes(buffer)
- if len(s) == 0 {
- b.Fatal(s)
- }
- }
- b.StopTimer()
- }
- func BenchmarkQuantityRoundUp(b *testing.B) {
- values := benchmarkQuantities()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- q := values[i%len(values)]
- copied := q
- copied.RoundUp(-3)
- }
- b.StopTimer()
- }
- func BenchmarkQuantityCopy(b *testing.B) {
- values := benchmarkQuantities()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- values[i%len(values)].Copy()
- }
- b.StopTimer()
- }
- func BenchmarkQuantityAdd(b *testing.B) {
- values := benchmarkQuantities()
- base := &Quantity{}
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- q := values[i%len(values)]
- base.d.Dec = nil
- base.i = int64Amount{value: 100}
- base.Add(q)
- }
- b.StopTimer()
- }
- func BenchmarkQuantityCmp(b *testing.B) {
- values := benchmarkQuantities()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- q := values[i%len(values)]
- if q.Cmp(q) != 0 {
- b.Fatal(q)
- }
- }
- b.StopTimer()
- }
|