diff --git a/glide.lock b/glide.lock index c17a44f5..9d965719 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: c8c998224f4cc27a742806398b8e81dec16a89ce83a8ec68a2e6e8e4692e8fe7 -updated: 2016-10-26T02:06:24.373221607-07:00 +hash: 8b25ad4ed6df28ab1f97f21f0744ff4fd42cba97cecad3443b4f1d039ca4f6cf +updated: 2017-01-25T15:30:44.303100067-08:00 imports: - name: github.com/coreos/go-semver version: 294930c1e79c64e7dbe360054274fdad492c8cf5 @@ -22,8 +22,4 @@ imports: - html/atom - name: gopkg.in/inf.v0 version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 -- name: k8s.io/kubernetes - version: 1bed5bb1a72be482ea507da3057b689d5a3034f1 - subpackages: - - pkg/api/resource testImports: [] diff --git a/glide.yaml b/glide.yaml index 84a65077..04c38592 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,4 +1,4 @@ -package: "github.com/appc/spec" +package: github.com/appc/spec import: - package: github.com/coreos/go-semver version: ~0.1.0 @@ -21,7 +21,3 @@ import: - html/atom - package: gopkg.in/inf.v0 version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 -- package: k8s.io/kubernetes - version: ~1.4.0 - subpackages: - - pkg/api/resource diff --git a/schema/types/isolator_resources.go b/schema/types/isolator_resources.go index 771c73fd..2ec250d4 100644 --- a/schema/types/isolator_resources.go +++ b/schema/types/isolator_resources.go @@ -19,7 +19,7 @@ import ( "errors" "fmt" - "k8s.io/kubernetes/pkg/api/resource" + "github.com/appc/spec/schema/types/resource" ) var ( diff --git a/schema/types/isolator_resources_test.go b/schema/types/isolator_resources_test.go index 747b7751..e53c15b8 100644 --- a/schema/types/isolator_resources_test.go +++ b/schema/types/isolator_resources_test.go @@ -18,7 +18,7 @@ import ( "reflect" "testing" - "k8s.io/kubernetes/pkg/api/resource" + "github.com/appc/spec/schema/types/resource" ) func mustQuantity(s string) *resource.Quantity { diff --git a/schema/types/resource/README.md b/schema/types/resource/README.md new file mode 100644 index 00000000..b3c16d25 --- /dev/null +++ b/schema/types/resource/README.md @@ -0,0 +1,4 @@ +This package was copied in from the Kubernetes repo to avoid a cyclic +dependency. These files were taken from master from +github.com/kubernetes/kubernetes at commit hash +b0deb2eb8f4037421077f77cb163dbb4c0a2a9f5. diff --git a/vendor/k8s.io/kubernetes/pkg/api/resource/amount.go b/schema/types/resource/amount.go similarity index 99% rename from vendor/k8s.io/kubernetes/pkg/api/resource/amount.go rename to schema/types/resource/amount.go index 2d3012c8..6ae823a0 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/resource/amount.go +++ b/schema/types/resource/amount.go @@ -1,5 +1,5 @@ /* -Copyright 2014 The Kubernetes Authors. +Copyright 2014 The Kubernetes Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/schema/types/resource/amount_test.go b/schema/types/resource/amount_test.go new file mode 100644 index 00000000..acaad630 --- /dev/null +++ b/schema/types/resource/amount_test.go @@ -0,0 +1,111 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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" +) + +func TestInt64AmountAsInt64(t *testing.T) { + for _, test := range []struct { + value int64 + scale Scale + result int64 + ok bool + }{ + {100, 0, 100, true}, + {100, 1, 1000, true}, + {100, -5, 0, false}, + {100, 100, 0, false}, + } { + r, ok := int64Amount{value: test.value, scale: test.scale}.AsInt64() + if r != test.result { + t.Errorf("%v: unexpected result: %d", test, r) + } + if ok != test.ok { + t.Errorf("%v: unexpected ok: %t", test, ok) + } + } +} + +func TestInt64AmountAdd(t *testing.T) { + for _, test := range []struct { + a, b, c int64Amount + ok bool + }{ + {int64Amount{value: 100, scale: 1}, int64Amount{value: 10, scale: 2}, int64Amount{value: 200, scale: 1}, true}, + {int64Amount{value: 100, scale: 1}, int64Amount{value: 1, scale: 2}, int64Amount{value: 110, scale: 1}, true}, + {int64Amount{value: 100, scale: 1}, int64Amount{value: 1, scale: 100}, int64Amount{value: 1, scale: 100}, false}, + {int64Amount{value: -5, scale: 2}, int64Amount{value: 50, scale: 1}, int64Amount{value: 0, scale: 1}, true}, + {int64Amount{value: -5, scale: 2}, int64Amount{value: 5, scale: 2}, int64Amount{value: 0, scale: 2}, true}, + + {int64Amount{value: mostPositive, scale: -1}, int64Amount{value: 1, scale: -1}, int64Amount{value: 0, scale: -1}, false}, + {int64Amount{value: mostPositive, scale: -1}, int64Amount{value: 0, scale: -1}, int64Amount{value: mostPositive, scale: -1}, true}, + {int64Amount{value: mostPositive / 10, scale: 1}, int64Amount{value: 10, scale: 0}, int64Amount{value: mostPositive, scale: -1}, false}, + } { + c := test.a + ok := c.Add(test.b) + if ok != test.ok { + t.Errorf("%v: unexpected ok: %t", test, ok) + } + if ok { + if c != test.c { + t.Errorf("%v: unexpected result: %d", test, c) + } + } else { + if c != test.a { + t.Errorf("%v: overflow addition mutated source: %d", test, c) + } + } + + // addition is commutative + c = test.b + if ok := c.Add(test.a); ok != test.ok { + t.Errorf("%v: unexpected ok: %t", test, ok) + } + if ok { + if c != test.c { + t.Errorf("%v: unexpected result: %d", test, c) + } + } else { + if c != test.b { + t.Errorf("%v: overflow addition mutated source: %d", test, c) + } + } + } +} +func TestInt64AsCanonicalString(t *testing.T) { + for _, test := range []struct { + value int64 + scale Scale + result string + exponent int32 + }{ + {100, 0, "100", 0}, + {100, 1, "1", 3}, + {100, -1, "10", 0}, + {10800, -10, "1080", -9}, + } { + r, exp := int64Amount{value: test.value, scale: test.scale}.AsCanonicalBytes(nil) + if string(r) != test.result { + t.Errorf("%v: unexpected result: %s", test, r) + } + if exp != test.exponent { + t.Errorf("%v: unexpected exponent: %d", test, exp) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/api/resource/math.go b/schema/types/resource/math.go similarity index 99% rename from vendor/k8s.io/kubernetes/pkg/api/resource/math.go rename to schema/types/resource/math.go index 887ac74c..163aafa5 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/resource/math.go +++ b/schema/types/resource/math.go @@ -1,5 +1,5 @@ /* -Copyright 2014 The Kubernetes Authors. +Copyright 2014 The Kubernetes Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/schema/types/resource/math_test.go b/schema/types/resource/math_test.go new file mode 100644 index 00000000..0fdda12e --- /dev/null +++ b/schema/types/resource/math_test.go @@ -0,0 +1,211 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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" +) + +func TestDetectOverflowAdd(t *testing.T) { + for _, test := range []struct { + a, b int64 + c int64 + ok bool + }{ + {0, 0, 0, true}, + {-1, 1, 0, true}, + {0, 1, 1, true}, + {2, 2, 4, true}, + {2, -2, 0, true}, + {-2, -2, -4, true}, + + {mostNegative, -1, 0, false}, + {mostNegative, 1, mostNegative + 1, true}, + {mostPositive, -1, mostPositive - 1, true}, + {mostPositive, 1, 0, false}, + + {mostNegative, mostPositive, -1, true}, + {mostPositive, mostNegative, -1, true}, + {mostPositive, mostPositive, 0, false}, + {mostNegative, mostNegative, 0, false}, + + {-mostPositive, mostNegative, 0, false}, + {mostNegative, -mostPositive, 0, false}, + {-mostPositive, -mostPositive, 0, false}, + } { + c, ok := int64Add(test.a, test.b) + if c != test.c { + t.Errorf("%v: unexpected result: %d", test, c) + } + if ok != test.ok { + t.Errorf("%v: unexpected overflow: %t", test, ok) + } + // addition is commutative + d, ok2 := int64Add(test.b, test.a) + if c != d || ok != ok2 { + t.Errorf("%v: not commutative: %d %t", test, d, ok2) + } + } +} + +func TestDetectOverflowMultiply(t *testing.T) { + for _, test := range []struct { + a, b int64 + c int64 + ok bool + }{ + {0, 0, 0, true}, + {-1, 1, -1, true}, + {-1, -1, 1, true}, + {1, 1, 1, true}, + {0, 1, 0, true}, + {1, 0, 0, true}, + {2, 2, 4, true}, + {2, -2, -4, true}, + {-2, -2, 4, true}, + + {mostNegative, -1, 0, false}, + {mostNegative, 1, mostNegative, true}, + {mostPositive, -1, -mostPositive, true}, + {mostPositive, 1, mostPositive, true}, + + {mostNegative, mostPositive, 0, false}, + {mostPositive, mostNegative, 0, false}, + {mostPositive, mostPositive, 1, false}, + {mostNegative, mostNegative, 0, false}, + + {-mostPositive, mostNegative, 0, false}, + {mostNegative, -mostPositive, 0, false}, + {-mostPositive, -mostPositive, 1, false}, + } { + c, ok := int64Multiply(test.a, test.b) + if c != test.c { + t.Errorf("%v: unexpected result: %d", test, c) + } + if ok != test.ok { + t.Errorf("%v: unexpected overflow: %t", test, ok) + } + // multiplication is commutative + d, ok2 := int64Multiply(test.b, test.a) + if c != d || ok != ok2 { + t.Errorf("%v: not commutative: %d %t", test, d, ok2) + } + } +} + +func TestDetectOverflowScale(t *testing.T) { + for _, a := range []int64{0, -1, 1, 10, -10, mostPositive, mostNegative, -mostPositive} { + for _, b := range []int64{1, 2, 10, 100, 1000, mostPositive} { + expect, expectOk := int64Multiply(a, b) + + c, ok := int64MultiplyScale(a, b) + if c != expect { + t.Errorf("%d*%d: unexpected result: %d", a, b, c) + } + if ok != expectOk { + t.Errorf("%d*%d: unexpected overflow: %t", a, b, ok) + } + } + for _, test := range []struct { + base int64 + fn func(a int64) (int64, bool) + }{ + {10, int64MultiplyScale10}, + {100, int64MultiplyScale100}, + {1000, int64MultiplyScale1000}, + } { + expect, expectOk := int64Multiply(a, test.base) + c, ok := test.fn(a) + if c != expect { + t.Errorf("%d*%d: unexpected result: %d", a, test.base, c) + } + if ok != expectOk { + t.Errorf("%d*%d: unexpected overflow: %t", a, test.base, ok) + } + } + } +} + +func TestRemoveInt64Factors(t *testing.T) { + for _, test := range []struct { + value int64 + max int64 + result int64 + scale int32 + }{ + {100, 10, 1, 2}, + {100, 10, 1, 2}, + {100, 100, 1, 1}, + {1, 10, 1, 0}, + } { + r, s := removeInt64Factors(test.value, test.max) + if r != test.result { + t.Errorf("%v: unexpected result: %d", test, r) + } + if s != test.scale { + t.Errorf("%v: unexpected scale: %d", test, s) + } + } +} + +func TestNegativeScaleInt64(t *testing.T) { + for _, test := range []struct { + base int64 + scale Scale + result int64 + exact bool + }{ + {1234567, 0, 1234567, true}, + {1234567, 1, 123457, false}, + {1234567, 2, 12346, false}, + {1234567, 3, 1235, false}, + {1234567, 4, 124, false}, + + {-1234567, 0, -1234567, true}, + {-1234567, 1, -123457, false}, + {-1234567, 2, -12346, false}, + {-1234567, 3, -1235, false}, + {-1234567, 4, -124, false}, + + {1000, 0, 1000, true}, + {1000, 1, 100, true}, + {1000, 2, 10, true}, + {1000, 3, 1, true}, + {1000, 4, 1, false}, + + {-1000, 0, -1000, true}, + {-1000, 1, -100, true}, + {-1000, 2, -10, true}, + {-1000, 3, -1, true}, + {-1000, 4, -1, false}, + + {0, 0, 0, true}, + {0, 1, 0, true}, + {0, 2, 0, true}, + + // negative scale is undefined behavior + {1000, -1, 1000, true}, + } { + result, exact := negativeScaleInt64(test.base, test.scale) + if result != test.result { + t.Errorf("%v: unexpected result: %d", test, result) + } + if exact != test.exact { + t.Errorf("%v: unexpected exact: %t", test, exact) + } + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/api/resource/quantity.go b/schema/types/resource/quantity.go similarity index 98% rename from vendor/k8s.io/kubernetes/pkg/api/resource/quantity.go rename to schema/types/resource/quantity.go index 823dd5ef..96877b4c 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/resource/quantity.go +++ b/schema/types/resource/quantity.go @@ -1,5 +1,5 @@ /* -Copyright 2014 The Kubernetes Authors. +Copyright 2014 The Kubernetes Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -87,6 +87,7 @@ import ( // writing some sort of special handling code in the hopes that that will // cause implementors to also use a fixed point implementation. // +// +gencopy=false // +protobuf=true // +protobuf.embed=string // +protobuf.options.marshal=false @@ -385,16 +386,6 @@ func ParseQuantity(str string) (Quantity, error) { return Quantity{d: infDecAmount{amount}, Format: format}, nil } -// DeepCopy returns a deep-copy of the Quantity value. Note that the method -// receiver is a value, so we can mutate it in-place and return it. -func (q Quantity) DeepCopy() Quantity { - if q.d.Dec != nil { - tmp := &inf.Dec{} - q.d.Dec = tmp.Set(q.d.Dec) - } - return q -} - // CanonicalizeBytes returns the canonical form of q and its suffix (see comment on Quantity). // // Note about BinarySI: diff --git a/schema/types/resource/quantity_example_test.go b/schema/types/resource/quantity_example_test.go new file mode 100644 index 00000000..104f8ea6 --- /dev/null +++ b/schema/types/resource/quantity_example_test.go @@ -0,0 +1,59 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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_test + +import ( + "fmt" + + "github.com/appc/spec/schema/types/resource" +) + +func ExampleFormat() { + memorySize := resource.NewQuantity(5*1024*1024*1024, resource.BinarySI) + fmt.Printf("memorySize = %v\n", memorySize) + + diskSize := resource.NewQuantity(5*1000*1000*1000, resource.DecimalSI) + fmt.Printf("diskSize = %v\n", diskSize) + + cores := resource.NewMilliQuantity(5300, resource.DecimalSI) + fmt.Printf("cores = %v\n", cores) + + // Output: + // memorySize = 5Gi + // diskSize = 5G + // cores = 5300m +} + +func ExampleMustParse() { + memorySize := resource.MustParse("5Gi") + fmt.Printf("memorySize = %v (%v)\n", memorySize.Value(), memorySize.Format) + + diskSize := resource.MustParse("5G") + fmt.Printf("diskSize = %v (%v)\n", diskSize.Value(), diskSize.Format) + + cores := resource.MustParse("5300m") + fmt.Printf("milliCores = %v (%v)\n", cores.MilliValue(), cores.Format) + + cores2 := resource.MustParse("5.4") + fmt.Printf("milliCores = %v (%v)\n", cores2.MilliValue(), cores2.Format) + + // Output: + // memorySize = 5368709120 (BinarySI) + // diskSize = 5000000000 (DecimalSI) + // milliCores = 5300 (DecimalSI) + // milliCores = 5400 (DecimalSI) +} diff --git a/schema/types/resource/quantity_test.go b/schema/types/resource/quantity_test.go new file mode 100644 index 00000000..5f2e7be0 --- /dev/null +++ b/schema/types/resource/quantity_test.go @@ -0,0 +1,1334 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 +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() +} diff --git a/vendor/k8s.io/kubernetes/pkg/api/resource/scale_int.go b/schema/types/resource/scale_int.go similarity index 97% rename from vendor/k8s.io/kubernetes/pkg/api/resource/scale_int.go rename to schema/types/resource/scale_int.go index 55e177b0..173de1a2 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/resource/scale_int.go +++ b/schema/types/resource/scale_int.go @@ -1,5 +1,5 @@ /* -Copyright 2015 The Kubernetes Authors. +Copyright 2015 The Kubernetes Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/schema/types/resource/scale_int_test.go b/schema/types/resource/scale_int_test.go new file mode 100644 index 00000000..1b4390e5 --- /dev/null +++ b/schema/types/resource/scale_int_test.go @@ -0,0 +1,85 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 ( + "math" + "math/big" + "testing" +) + +func TestScaledValueInternal(t *testing.T) { + tests := []struct { + unscaled *big.Int + scale int + newScale int + + want int64 + }{ + // remain scale + {big.NewInt(1000), 0, 0, 1000}, + + // scale down + {big.NewInt(1000), 0, -3, 1}, + {big.NewInt(1000), 3, 0, 1}, + {big.NewInt(0), 3, 0, 0}, + + // always round up + {big.NewInt(999), 3, 0, 1}, + {big.NewInt(500), 3, 0, 1}, + {big.NewInt(499), 3, 0, 1}, + {big.NewInt(1), 3, 0, 1}, + // large scaled value does not lose precision + {big.NewInt(0).Sub(maxInt64, bigOne), 1, 0, (math.MaxInt64-1)/10 + 1}, + // large intermidiate result. + {big.NewInt(1).Exp(big.NewInt(10), big.NewInt(100), nil), 100, 0, 1}, + + // scale up + {big.NewInt(0), 0, 3, 0}, + {big.NewInt(1), 0, 3, 1000}, + {big.NewInt(1), -3, 0, 1000}, + {big.NewInt(1000), -3, 2, 100000000}, + {big.NewInt(0).Div(big.NewInt(math.MaxInt64), bigThousand), 0, 3, + (math.MaxInt64 / 1000) * 1000}, + } + + for i, tt := range tests { + old := (&big.Int{}).Set(tt.unscaled) + got := scaledValue(tt.unscaled, tt.scale, tt.newScale) + if got != tt.want { + t.Errorf("#%d: got = %v, want %v", i, got, tt.want) + } + if tt.unscaled.Cmp(old) != 0 { + t.Errorf("#%d: unscaled = %v, want %v", i, tt.unscaled, old) + } + } +} + +func BenchmarkScaledValueSmall(b *testing.B) { + s := big.NewInt(1000) + for i := 0; i < b.N; i++ { + scaledValue(s, 3, 0) + } +} + +func BenchmarkScaledValueLarge(b *testing.B) { + s := big.NewInt(math.MaxInt64) + s.Mul(s, big.NewInt(1000)) + for i := 0; i < b.N; i++ { + scaledValue(s, 10, 0) + } +} diff --git a/vendor/k8s.io/kubernetes/pkg/api/resource/suffix.go b/schema/types/resource/suffix.go similarity index 98% rename from vendor/k8s.io/kubernetes/pkg/api/resource/suffix.go rename to schema/types/resource/suffix.go index 5ed7abe6..0aa2ce2b 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/resource/suffix.go +++ b/schema/types/resource/suffix.go @@ -1,5 +1,5 @@ /* -Copyright 2014 The Kubernetes Authors. +Copyright 2014 The Kubernetes Authors All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/k8s.io/kubernetes/LICENSE b/vendor/k8s.io/kubernetes/LICENSE deleted file mode 100644 index 00b24011..00000000 --- a/vendor/k8s.io/kubernetes/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - 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. diff --git a/vendor/k8s.io/kubernetes/pkg/api/resource/generated.pb.go b/vendor/k8s.io/kubernetes/pkg/api/resource/generated.pb.go deleted file mode 100644 index 3bde1525..00000000 --- a/vendor/k8s.io/kubernetes/pkg/api/resource/generated.pb.go +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2016 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. -*/ - -// Code generated by protoc-gen-gogo. -// source: k8s.io/kubernetes/pkg/api/resource/generated.proto -// DO NOT EDIT! - -/* - Package resource is a generated protocol buffer package. - - It is generated from these files: - k8s.io/kubernetes/pkg/api/resource/generated.proto - - It has these top-level messages: - Quantity -*/ -package resource - -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -const _ = proto.GoGoProtoPackageIsVersion1 - -func (m *Quantity) Reset() { *m = Quantity{} } -func (*Quantity) ProtoMessage() {} -func (*Quantity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} } - -func init() { - proto.RegisterType((*Quantity)(nil), "k8s.io.kubernetes.pkg.api.resource.Quantity") -} - -var fileDescriptorGenerated = []byte{ - // 222 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x32, 0xca, 0xb6, 0x28, 0xd6, - 0xcb, 0xcc, 0xd7, 0xcf, 0x2e, 0x4d, 0x4a, 0x2d, 0xca, 0x4b, 0x2d, 0x49, 0x2d, 0xd6, 0x2f, 0xc8, - 0x4e, 0xd7, 0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0x4a, 0x2d, 0xce, 0x2f, 0x2d, 0x4a, 0x4e, 0xd5, 0x4f, - 0x4f, 0xcd, 0x4b, 0x2d, 0x4a, 0x2c, 0x49, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, - 0x82, 0xe8, 0xd1, 0x43, 0xe8, 0xd1, 0x03, 0xea, 0xd1, 0x03, 0xea, 0xd1, 0x83, 0xe9, 0x91, 0xd2, - 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0x4f, 0xcf, 0xd7, - 0x07, 0x6b, 0x4d, 0x2a, 0x4d, 0x03, 0xf3, 0xc0, 0x1c, 0x30, 0x0b, 0x62, 0xa4, 0x94, 0x21, 0x76, - 0x67, 0x94, 0x96, 0x64, 0xe6, 0xe8, 0x67, 0xe6, 0x95, 0x14, 0x97, 0x14, 0xa1, 0xbb, 0x42, 0xc9, - 0x82, 0x8b, 0x23, 0xb0, 0x34, 0x31, 0xaf, 0x24, 0xb3, 0xa4, 0x52, 0x48, 0x8c, 0x8b, 0x0d, 0xa8, - 0x24, 0x33, 0x2f, 0x5d, 0x82, 0x51, 0x81, 0x51, 0x83, 0x33, 0x08, 0xca, 0xb3, 0x12, 0x99, 0xb1, - 0x40, 0x9e, 0xa1, 0x63, 0xa1, 0x3c, 0xc3, 0x04, 0x20, 0x5e, 0x00, 0xc4, 0x0d, 0x77, 0x14, 0x18, - 0x9c, 0xb4, 0x4e, 0x3c, 0x94, 0x63, 0xb8, 0x00, 0xc4, 0x37, 0x80, 0xb8, 0xe1, 0x91, 0x1c, 0xe3, - 0x09, 0x20, 0xbe, 0x00, 0xc4, 0x0f, 0x80, 0x78, 0xc2, 0x63, 0x39, 0x86, 0x28, 0x0e, 0x98, 0x3f, - 0x00, 0x01, 0x00, 0x00, 0xff, 0xff, 0x90, 0x1c, 0x7f, 0xff, 0x20, 0x01, 0x00, 0x00, -} diff --git a/vendor/k8s.io/kubernetes/pkg/api/resource/quantity_proto.go b/vendor/k8s.io/kubernetes/pkg/api/resource/quantity_proto.go deleted file mode 100644 index 74dfb4e4..00000000 --- a/vendor/k8s.io/kubernetes/pkg/api/resource/quantity_proto.go +++ /dev/null @@ -1,284 +0,0 @@ -/* -Copyright 2015 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 ( - "fmt" - "io" - - "github.com/gogo/protobuf/proto" -) - -var _ proto.Sizer = &Quantity{} - -func (m *Quantity) Marshal() (data []byte, err error) { - size := m.Size() - data = make([]byte, size) - n, err := m.MarshalTo(data) - if err != nil { - return nil, err - } - return data[:n], nil -} - -// MarshalTo is a customized version of the generated Protobuf unmarshaler for a struct -// with a single string field. -func (m *Quantity) MarshalTo(data []byte) (int, error) { - var i int - _ = i - var l int - _ = l - - data[i] = 0xa - i++ - // BEGIN CUSTOM MARSHAL - out := m.String() - i = encodeVarintGenerated(data, i, uint64(len(out))) - i += copy(data[i:], out) - // END CUSTOM MARSHAL - - return i, nil -} - -func encodeVarintGenerated(data []byte, offset int, v uint64) int { - for v >= 1<<7 { - data[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - data[offset] = uint8(v) - return offset + 1 -} - -func (m *Quantity) Size() (n int) { - var l int - _ = l - - // BEGIN CUSTOM SIZE - l = len(m.String()) - // END CUSTOM SIZE - - n += 1 + l + sovGenerated(uint64(l)) - return n -} - -func sovGenerated(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} - -// Unmarshal is a customized version of the generated Protobuf unmarshaler for a struct -// with a single string field. -func (m *Quantity) Unmarshal(data []byte) error { - l := len(data) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Quantity: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Quantity: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field String_", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenerated - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenerated - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - s := string(data[iNdEx:postIndex]) - - // BEGIN CUSTOM DECODE - p, err := ParseQuantity(s) - if err != nil { - return err - } - *m = p - // END CUSTOM DECODE - - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenerated(data[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthGenerated - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} - -func skipGenerated(data []byte) (n int, err error) { - l := len(data) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenerated - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenerated - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if data[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenerated - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - iNdEx += length - if length < 0 { - return 0, ErrInvalidLengthGenerated - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenerated - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipGenerated(data[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") -} - -var ( - ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow") -)