diff --git a/staging/src/k8s.io/apimachinery/pkg/api/resource/BUILD b/staging/src/k8s.io/apimachinery/pkg/api/resource/BUILD index 19e60a66334..571a6b1e91d 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/resource/BUILD +++ b/staging/src/k8s.io/apimachinery/pkg/api/resource/BUILD @@ -13,6 +13,7 @@ go_test( srcs = [ "amount_test.go", "math_test.go", + "quantity_proto_test.go", "quantity_test.go", "scale_int_test.go", ], diff --git a/staging/src/k8s.io/apimachinery/pkg/api/resource/amount_test.go b/staging/src/k8s.io/apimachinery/pkg/api/resource/amount_test.go index ae5e1fc9c30..dd070bad36b 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/resource/amount_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/resource/amount_test.go @@ -109,3 +109,25 @@ func TestInt64AsCanonicalString(t *testing.T) { } } } + +func TestAmountSign(t *testing.T) { + table := []struct { + i int64Amount + expect int + }{ + {int64Amount{value: -50, scale: 1}, -1}, + {int64Amount{value: 0, scale: 1}, 0}, + {int64Amount{value: 300, scale: 1}, 1}, + {int64Amount{value: -50, scale: -8}, -1}, + {int64Amount{value: 50, scale: -8}, 1}, + {int64Amount{value: 0, scale: -8}, 0}, + {int64Amount{value: -50, scale: 0}, -1}, + {int64Amount{value: 50, scale: 0}, 1}, + {int64Amount{value: 0, scale: 0}, 0}, + } + for _, testCase := range table { + if result := testCase.i.Sign(); result != testCase.expect { + t.Errorf("i: %v, Expected: %v, Actual: %v", testCase.i, testCase.expect, result) + } + } +} diff --git a/staging/src/k8s.io/apimachinery/pkg/api/resource/math.go b/staging/src/k8s.io/apimachinery/pkg/api/resource/math.go index 887ac74c984..72d3880c028 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/resource/math.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/resource/math.go @@ -247,19 +247,6 @@ func pow10Int64(b int64) int64 { } } -// powInt64 raises a to the bth power. Is not overflow aware. -func powInt64(a, b int64) int64 { - p := int64(1) - for b > 0 { - if b&1 != 0 { - p *= a - } - b >>= 1 - a *= a - } - return p -} - // negativeScaleInt64 returns the result of dividing base by scale * 10 and the remainder, or // false if no such division is possible. Dividing by negative scales is undefined. func divideByScaleInt64(base int64, scale Scale) (result, remainder int64, exact bool) { diff --git a/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_proto_test.go b/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_proto_test.go new file mode 100644 index 00000000000..574a3cf5d73 --- /dev/null +++ b/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_proto_test.go @@ -0,0 +1,103 @@ +/* +Copyright 2017 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 ( + "testing" + + inf "gopkg.in/inf.v0" +) + +func TestQuantityProtoMarshal(t *testing.T) { + // Test when d is nil + table := []struct { + quantity string + expect Quantity + }{ + {"0", Quantity{i: int64Amount{value: 0, scale: 0}, s: "0", Format: DecimalSI}}, + {"100m", Quantity{i: int64Amount{value: 100, scale: -3}, s: "100m", Format: DecimalSI}}, + {"50m", Quantity{i: int64Amount{value: 50, scale: -3}, s: "50m", Format: DecimalSI}}, + {"10000T", Quantity{i: int64Amount{value: 10000, scale: 12}, s: "10000T", Format: DecimalSI}}, + } + for _, testCase := range table { + q := MustParse(testCase.quantity) + // Won't currently get an error as MarshalTo can't return one + result, _ := q.Marshal() + q.MarshalTo(result) + if q.Cmp(testCase.expect) != 0 { + t.Errorf("Expected: %v, Actual: %v", testCase.expect, q) + } + } + // Test when i is {0,0} + table2 := []struct { + dec *inf.Dec + expect Quantity + }{ + {dec(0, 0).Dec, Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(0, 0).Dec}, s: "0", Format: DecimalSI}}, + {dec(10, 0).Dec, Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(10, 0).Dec}, s: "10", Format: DecimalSI}}, + {dec(-10, 0).Dec, Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(-10, 0).Dec}, s: "-10", Format: DecimalSI}}, + } + for _, testCase := range table2 { + q := Quantity{d: infDecAmount{testCase.dec}, Format: DecimalSI} + // Won't currently get an error as MarshalTo can't return one + result, _ := q.Marshal() + q.Unmarshal(result) + if q.Cmp(testCase.expect) != 0 { + t.Errorf("Expected: %v, Actual: %v", testCase.expect, q) + } + } +} + +func TestQuantityProtoUnmarshal(t *testing.T) { + // Test when d is nil + table := []struct { + input Quantity + expect string + }{ + {Quantity{i: int64Amount{value: 0, scale: 0}, s: "0", Format: DecimalSI}, "0"}, + {Quantity{i: int64Amount{value: 100, scale: -3}, s: "100m", Format: DecimalSI}, "100m"}, + {Quantity{i: int64Amount{value: 50, scale: -3}, s: "50m", Format: DecimalSI}, "50m"}, + {Quantity{i: int64Amount{value: 10000, scale: 12}, s: "10000T", Format: DecimalSI}, "10000T"}, + } + for _, testCase := range table { + var inputQ Quantity + expectQ := MustParse(testCase.expect) + inputByteArray, _ := testCase.input.Marshal() + inputQ.Unmarshal(inputByteArray) + if inputQ.Cmp(expectQ) != 0 { + t.Errorf("Expected: %v, Actual: %v", inputQ, expectQ) + } + } + // Test when i is {0,0} + table2 := []struct { + input Quantity + expect *inf.Dec + }{ + {Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(0, 0).Dec}, s: "0", Format: DecimalSI}, dec(0, 0).Dec}, + {Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(10, 0).Dec}, s: "10", Format: DecimalSI}, dec(10, 0).Dec}, + {Quantity{i: int64Amount{value: 0, scale: 0}, d: infDecAmount{dec(-10, 0).Dec}, s: "-10", Format: DecimalSI}, dec(-10, 0).Dec}, + } + for _, testCase := range table2 { + var inputQ Quantity + expectQ := Quantity{d: infDecAmount{testCase.expect}, Format: DecimalSI} + inputByteArray, _ := testCase.input.Marshal() + inputQ.Unmarshal(inputByteArray) + if inputQ.Cmp(expectQ) != 0 { + t.Errorf("Expected: %v, Actual: %v", inputQ, expectQ) + } + } +} diff --git a/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_test.go b/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_test.go index a60e8851cbd..e61a2547d45 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity_test.go @@ -79,6 +79,17 @@ func TestQuantityParseZero(t *testing.T) { } } +// TestQuantityParseNonNumericError ensures that when a non-numeric string is parsed +// it panics +func TestQuantityParseNonNumericPanic(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Errorf("MustParse did not panic") + } + }() + _ = MustParse("Non-Numeric") +} + // 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) { @@ -140,6 +151,7 @@ func TestQuantityCanocicalizeZero(t *testing.T) { } func TestQuantityCmp(t *testing.T) { + // Test when d is nil table := []struct { x string y string @@ -157,8 +169,8 @@ func TestQuantityCmp(t *testing.T) { t.Errorf("X: %v, Y: %v, Expected: %v, Actual: %v", testCase.x, testCase.y, testCase.expect, result) } } - - nils := []struct { + // Test when i is {0,0} + table2 := []struct { x *inf.Dec y *inf.Dec expect int @@ -172,11 +184,11 @@ func TestQuantityCmp(t *testing.T) { {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) + for _, testCase := range table2 { + q1 := Quantity{d: infDecAmount{testCase.x}, Format: DecimalSI} + q2 := Quantity{d: infDecAmount{testCase.y}, Format: DecimalSI} + 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) } } } @@ -799,6 +811,34 @@ var fuzzer = fuzz.New().Funcs( }, ) +func TestQuantityDeepCopy(t *testing.T) { + // Test when d is nil + slice := []string{"0", "100m", "50m", "10000T"} + for _, testCase := range slice { + q := MustParse(testCase) + if result := q.DeepCopy(); result != q { + t.Errorf("Expected: %v, Actual: %v", q, result) + } + } + table := []*inf.Dec{ + dec(0, 0).Dec, + dec(10, 0).Dec, + dec(-10, 0).Dec, + } + // Test when i is {0,0} + for _, testCase := range table { + q := Quantity{d: infDecAmount{testCase}, Format: DecimalSI} + result := q.DeepCopy() + if q.d.Cmp(result.AsDec()) != 0 { + t.Errorf("Expected: %v, Actual: %v", q.String(), result.String()) + } + result = Quantity{d: infDecAmount{dec(2, 0).Dec}, Format: DecimalSI} + if q.d.Cmp(result.AsDec()) == 0 { + t.Errorf("Modifying result has affected q") + } + } +} + func TestJSON(t *testing.T) { for i := 0; i < 500; i++ { q := &Quantity{}