Add accessor functions; round-trip test

This commit is contained in:
Daniel Smith
2015-01-02 13:42:27 -08:00
parent 18b896645c
commit 6c6cdac0e9
3 changed files with 348 additions and 91 deletions

View File

@@ -18,8 +18,10 @@ package resource
import (
//"reflect"
"encoding/json"
"testing"
fuzz "github.com/google/gofuzz"
"speter.net/go/exp/math/dec/inf"
)
@@ -112,7 +114,7 @@ func TestQuantityParse(t *testing.T) {
{"10.035M", Quantity{dec(10035, 3), DecimalSI}},
{"1.2e3", Quantity{dec(12, 2), DecimalExponent}},
{"1.3E6", Quantity{dec(13, 5), DecimalExponent}},
{"1.3E+6", Quantity{dec(13, 5), DecimalExponent}},
{"1.40e9", Quantity{dec(14, 8), DecimalExponent}},
{"1.53E12", Quantity{dec(153, 10), DecimalExponent}},
{"1.6e15", Quantity{dec(16, 14), DecimalExponent}},
@@ -141,6 +143,21 @@ func TestQuantityParse(t *testing.T) {
{"9Ei", Quantity{maxAllowed, BinarySI}},
{"9223372036854775807Ki", Quantity{maxAllowed, BinarySI}},
{"12E", Quantity{maxAllowed, DecimalSI}},
// We'll accept fractional binary stuff, too.
{"100.035Ki", Quantity{dec(10243584, -2), BinarySI}},
{"0.5Mi", Quantity{dec(.5*1024*1024, 0), BinarySI}},
{"0.05Gi", Quantity{dec(536870912, -1), BinarySI}},
{"0.025Ti", Quantity{dec(274877906944, -1), BinarySI}},
// These get rounded though
{"0.0001i", Quantity{dec(1, -3), DecimalSI}},
{"0.005i", Quantity{dec(5, -3), DecimalSI}},
{"0.05i", Quantity{dec(50, -3), DecimalSI}},
// Also, if below you expect (512, -3), you're wrong in two ways:
// In the sequence [1024*1024*1024, 1024*1024, 1024, ?], the last term is "1" not 1/1024.
// Even if it were, 500 * 1/1024 = .48828125, NOT .512
// I cannot recommend using this feature, it is confusing.
{"0.5i", Quantity{dec(500, -3), DecimalSI}},
}
for _, item := range table {
@@ -194,14 +211,6 @@ func TestQuantityParse(t *testing.T) {
"1+1.0M",
"0.1mi",
"0.1am",
"0.0001i",
"100.035Ki",
"0.5Mi",
"0.05Gi",
"0.5Ti",
"0.005i",
"0.05i",
"0.5i",
"aoeu",
}
for _, item := range invalid {
@@ -223,17 +232,20 @@ func TestQuantityString(t *testing.T) {
{Quantity{dec(1001*1024*1024*1024, 0), BinarySI}, "1001Gi"},
{Quantity{dec(1024*1024*1024*1024, 0), BinarySI}, "1Ti"},
{Quantity{dec(5, 0), BinarySI}, "5i"},
{Quantity{dec(500, -3), BinarySI}, "500m"},
{Quantity{dec(1, 9), DecimalSI}, "1G"},
{Quantity{dec(1000, 6), DecimalSI}, "1G"},
{Quantity{dec(1000000, 3), DecimalSI}, "1G"},
{Quantity{dec(1000000000, 0), DecimalSI}, "1G"},
{Quantity{dec(1, -3), DecimalSI}, "1m"},
{Quantity{dec(80, -3), DecimalSI}, "80m"},
{Quantity{dec(1080, -3), DecimalSI}, "1.080"},
{Quantity{dec(108, -2), DecimalSI}, "1.080"},
{Quantity{dec(10800, -4), DecimalSI}, "1.080"},
{Quantity{dec(1080, -3), DecimalSI}, "1080m"},
{Quantity{dec(108, -2), DecimalSI}, "1080m"},
{Quantity{dec(10800, -4), DecimalSI}, "1080m"},
{Quantity{dec(300, 6), DecimalSI}, "300M"},
{Quantity{dec(1, 12), DecimalSI}, "1T"},
{Quantity{dec(1234567, 6), DecimalSI}, "1234567M"},
{Quantity{dec(1234567, -3), BinarySI}, "1235i"},
{Quantity{dec(3, 3), DecimalSI}, "3k"},
{Quantity{dec(0, 0), DecimalSI}, "0"},
{Quantity{dec(0, 0), BinarySI}, "0i"},
@@ -266,3 +278,150 @@ func TestQuantityString(t *testing.T) {
}
}
}
var fuzzer = fuzz.New().Funcs(
func(q *Quantity, c fuzz.Continue) {
q.Amount = &inf.Dec{}
if c.RandBool() {
q.Format = BinarySI
if c.RandBool() {
q.Amount.SetScale(0)
q.Amount.SetUnscaled(c.Int63())
return
}
// Be sure to test cases like 1Mi
q.Amount.SetScale(0)
q.Amount.SetUnscaled(c.Int63n(1024) << uint(10*c.Intn(5)))
return
}
if c.RandBool() {
q.Format = DecimalSI
} else {
q.Format = DecimalExponent
}
if c.RandBool() {
q.Amount.SetScale(inf.Scale(c.Intn(4)))
q.Amount.SetUnscaled(c.Int63())
return
}
// Be sure to test cases like 1M
q.Amount.SetScale(inf.Scale(3 - c.Intn(15)))
q.Amount.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", q)
}
q2 := &Quantity{}
err = json.Unmarshal(b, q2)
if err != nil {
t.Errorf("%v: error decoding %v", q, string(b))
}
if q2.Amount.Cmp(q.Amount) != 0 {
t.Errorf("Expected equal: %v, %v (json was '%v')", q, q2, string(b))
}
}
}
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, "2i", false}, // Rounded up
{1000000, "invalidFormatDefaultsToExponent", "1e3", true},
{1024 * 1024, BinarySI, "1049i", false},
}
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 _, item := range table {
q := NewQuantity(item.value, item.format)
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 e, a := item.expect, q.String(); e != a {
t.Errorf("Set: Expected %v, got %v; %#v", e, a, q)
}
}
}
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")
}
}