|
|
@@ -0,0 +1,454 @@
|
|
|
+package dec
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "encoding/gob"
|
|
|
+ "fmt"
|
|
|
+ "math/big"
|
|
|
+ "strings"
|
|
|
+ "testing"
|
|
|
+)
|
|
|
+
|
|
|
+type decFunZZ func(z, x, y *Dec) *Dec
|
|
|
+type decArgZZ struct {
|
|
|
+ z, x, y *Dec
|
|
|
+}
|
|
|
+
|
|
|
+var decSumZZ = []decArgZZ{
|
|
|
+ {NewDecInt64(0), NewDecInt64(0), NewDecInt64(0)},
|
|
|
+ {NewDecInt64(1), NewDecInt64(1), NewDecInt64(0)},
|
|
|
+ {NewDecInt64(1111111110), NewDecInt64(123456789), NewDecInt64(987654321)},
|
|
|
+ {NewDecInt64(-1), NewDecInt64(-1), NewDecInt64(0)},
|
|
|
+ {NewDecInt64(864197532), NewDecInt64(-123456789), NewDecInt64(987654321)},
|
|
|
+ {NewDecInt64(-1111111110), NewDecInt64(-123456789), NewDecInt64(-987654321)},
|
|
|
+ {NewDec(big.NewInt(12), 2), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 2)},
|
|
|
+}
|
|
|
+
|
|
|
+var decProdZZ = []decArgZZ{
|
|
|
+ {NewDecInt64(0), NewDecInt64(0), NewDecInt64(0)},
|
|
|
+ {NewDecInt64(0), NewDecInt64(1), NewDecInt64(0)},
|
|
|
+ {NewDecInt64(1), NewDecInt64(1), NewDecInt64(1)},
|
|
|
+ {NewDecInt64(-991 * 991), NewDecInt64(991), NewDecInt64(-991)},
|
|
|
+ {NewDec(big.NewInt(2), 3), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 2)},
|
|
|
+ {NewDec(big.NewInt(2), -3), NewDec(big.NewInt(1), -1), NewDec(big.NewInt(2), -2)},
|
|
|
+ {NewDec(big.NewInt(2), 3), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 2)},
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecSignZ(t *testing.T) {
|
|
|
+ var zero Dec
|
|
|
+ for _, a := range decSumZZ {
|
|
|
+ s := a.z.Sign()
|
|
|
+ e := a.z.Cmp(&zero)
|
|
|
+ if s != e {
|
|
|
+ t.Errorf("got %d; want %d for z = %v", s, e, a.z)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecAbsZ(t *testing.T) {
|
|
|
+ var zero Dec
|
|
|
+ for _, a := range decSumZZ {
|
|
|
+ var z Dec
|
|
|
+ z.Abs(a.z)
|
|
|
+ var e Dec
|
|
|
+ e.Set(a.z)
|
|
|
+ if e.Cmp(&zero) < 0 {
|
|
|
+ e.Sub(&zero, &e)
|
|
|
+ }
|
|
|
+ if z.Cmp(&e) != 0 {
|
|
|
+ t.Errorf("got z = %v; want %v", z, e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func testDecFunZZ(t *testing.T, msg string, f decFunZZ, a decArgZZ) {
|
|
|
+ var z Dec
|
|
|
+ f(&z, a.x, a.y)
|
|
|
+ if (&z).Cmp(a.z) != 0 {
|
|
|
+ t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecSumZZ(t *testing.T) {
|
|
|
+ AddZZ := func(z, x, y *Dec) *Dec { return z.Add(x, y) }
|
|
|
+ SubZZ := func(z, x, y *Dec) *Dec { return z.Sub(x, y) }
|
|
|
+ for _, a := range decSumZZ {
|
|
|
+ arg := a
|
|
|
+ testDecFunZZ(t, "AddZZ", AddZZ, arg)
|
|
|
+
|
|
|
+ arg = decArgZZ{a.z, a.y, a.x}
|
|
|
+ testDecFunZZ(t, "AddZZ symmetric", AddZZ, arg)
|
|
|
+
|
|
|
+ arg = decArgZZ{a.x, a.z, a.y}
|
|
|
+ testDecFunZZ(t, "SubZZ", SubZZ, arg)
|
|
|
+
|
|
|
+ arg = decArgZZ{a.y, a.z, a.x}
|
|
|
+ testDecFunZZ(t, "SubZZ symmetric", SubZZ, arg)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecProdZZ(t *testing.T) {
|
|
|
+ MulZZ := func(z, x, y *Dec) *Dec { return z.Mul(x, y) }
|
|
|
+ for _, a := range decProdZZ {
|
|
|
+ arg := a
|
|
|
+ testDecFunZZ(t, "MulZZ", MulZZ, arg)
|
|
|
+
|
|
|
+ arg = decArgZZ{a.z, a.y, a.x}
|
|
|
+ testDecFunZZ(t, "MulZZ symmetric", MulZZ, arg)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+var decQuoRemZZZ = []struct {
|
|
|
+ z, x, y *Dec
|
|
|
+ r *big.Rat
|
|
|
+ srA, srB int
|
|
|
+}{
|
|
|
+ // basic examples
|
|
|
+ {NewDec(big.NewInt(1), 0), NewDecInt64(2), NewDecInt64(2), big.NewRat(0, 1), 0, 1},
|
|
|
+ {NewDec(big.NewInt(15), 1), NewDecInt64(3), NewDecInt64(2), big.NewRat(0, 1), 0, 1},
|
|
|
+ {NewDec(big.NewInt(1), 1), NewDecInt64(1), NewDecInt64(10), big.NewRat(0, 1), 0, 1},
|
|
|
+ {NewDec(big.NewInt(0), 0), NewDecInt64(2), NewDecInt64(3), big.NewRat(2, 3), 1, 1},
|
|
|
+ {NewDec(big.NewInt(0), 0), NewDecInt64(2), NewDecInt64(6), big.NewRat(1, 3), 1, 1},
|
|
|
+ {NewDec(big.NewInt(1), 1), NewDecInt64(2), NewDecInt64(12), big.NewRat(2, 3), 1, 1},
|
|
|
+
|
|
|
+ // examples from the Go Language Specification
|
|
|
+ {NewDec(big.NewInt(1), 0), NewDecInt64(5), NewDecInt64(3), big.NewRat(2, 3), 1, 1},
|
|
|
+ {NewDec(big.NewInt(-1), 0), NewDecInt64(-5), NewDecInt64(3), big.NewRat(-2, 3), -1, 1},
|
|
|
+ {NewDec(big.NewInt(-1), 0), NewDecInt64(5), NewDecInt64(-3), big.NewRat(-2, 3), 1, -1},
|
|
|
+ {NewDec(big.NewInt(1), 0), NewDecInt64(-5), NewDecInt64(-3), big.NewRat(2, 3), -1, -1},
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecQuoRem(t *testing.T) {
|
|
|
+ for i, a := range decQuoRemZZZ {
|
|
|
+ z, rA, rB := new(Dec), new(big.Int), new(big.Int)
|
|
|
+ s := ScaleQuoExact(a.x, a.y)
|
|
|
+ z.quoRem(a.x, a.y, s, true, rA, rB)
|
|
|
+ if a.z.Cmp(z) != 0 || a.r.Cmp(new(big.Rat).SetFrac(rA, rB)) != 0 {
|
|
|
+ t.Errorf("#%d QuoRemZZZ got %v, %v, %v; expected %v, %v", i, z, rA, rB, a.z, a.r)
|
|
|
+ }
|
|
|
+ if a.srA != rA.Sign() || a.srB != rB.Sign() {
|
|
|
+ t.Errorf("#%d QuoRemZZZ wrong signs, got %v, %v; expected %v, %v", i, rA.Sign(), rB.Sign(), a.srA, a.srB)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+var rounderInputs = [...]struct {
|
|
|
+ quo *Dec
|
|
|
+ rA, rB *big.Int
|
|
|
+}{
|
|
|
+ // examples from go language spec
|
|
|
+ {NewDec(big.NewInt(1), 0), big.NewInt(2), big.NewInt(3)}, // 5 / 3
|
|
|
+ {NewDec(big.NewInt(-1), 0), big.NewInt(-2), big.NewInt(3)}, // -5 / 3
|
|
|
+ {NewDec(big.NewInt(-1), 0), big.NewInt(2), big.NewInt(-3)}, // 5 / -3
|
|
|
+ {NewDec(big.NewInt(1), 0), big.NewInt(-2), big.NewInt(-3)}, // -5 / -3
|
|
|
+ // examples from godoc
|
|
|
+ {NewDec(big.NewInt(-1), 1), big.NewInt(-8), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(-1), 1), big.NewInt(-5), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(-1), 1), big.NewInt(-2), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(0), 1), big.NewInt(-8), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(0), 1), big.NewInt(-5), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(0), 1), big.NewInt(-2), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(0), 1), big.NewInt(0), big.NewInt(1)},
|
|
|
+ {NewDec(big.NewInt(0), 1), big.NewInt(2), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(0), 1), big.NewInt(5), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(0), 1), big.NewInt(8), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(1), 1), big.NewInt(2), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(1), 1), big.NewInt(5), big.NewInt(10)},
|
|
|
+ {NewDec(big.NewInt(1), 1), big.NewInt(8), big.NewInt(10)},
|
|
|
+}
|
|
|
+
|
|
|
+var rounderResults = [...]struct {
|
|
|
+ rounder Rounder
|
|
|
+ results [len(rounderInputs)]*Dec
|
|
|
+}{
|
|
|
+ {RoundExact, [...]*Dec{nil, nil, nil, nil,
|
|
|
+ nil, nil, nil, nil, nil, nil,
|
|
|
+ NewDec(big.NewInt(0), 1), nil, nil, nil, nil, nil, nil}},
|
|
|
+ {RoundDown, [...]*Dec{
|
|
|
+ NewDecInt64(1), NewDecInt64(-1), NewDecInt64(-1), NewDecInt64(1),
|
|
|
+ NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
|
|
|
+ NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1)}},
|
|
|
+ {RoundUp, [...]*Dec{
|
|
|
+ NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
|
|
|
+ NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1),
|
|
|
+ NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
|
|
|
+ NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
|
|
|
+ NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
|
|
|
+ {RoundHalfDown, [...]*Dec{
|
|
|
+ NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
|
|
|
+ NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
|
|
|
+ NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(1), 1),
|
|
|
+ NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 1)}},
|
|
|
+ {RoundHalfUp, [...]*Dec{
|
|
|
+ NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
|
|
|
+ NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-1), 1),
|
|
|
+ NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(0), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
|
|
|
+ NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
|
|
|
+ {RoundFloor, [...]*Dec{
|
|
|
+ NewDecInt64(1), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(1),
|
|
|
+ NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1),
|
|
|
+ NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
|
|
|
+ NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1)}},
|
|
|
+ {RoundCeil, [...]*Dec{
|
|
|
+ NewDecInt64(2), NewDecInt64(-1), NewDecInt64(-1), NewDecInt64(2),
|
|
|
+ NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
|
|
|
+ NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(0), 1),
|
|
|
+ NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
|
|
|
+ NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
|
|
|
+}
|
|
|
+
|
|
|
+func TestRound(t *testing.T) {
|
|
|
+ for i, a := range rounderResults {
|
|
|
+ for j, input := range rounderInputs {
|
|
|
+ q := new(Dec).Set(input.quo)
|
|
|
+ rA, rB := new(big.Int).Set(input.rA), new(big.Int).Set(input.rB)
|
|
|
+ res := a.rounder.Round(new(Dec), q, rA, rB)
|
|
|
+ if a.results[j] == nil && res == nil {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if (a.results[j] == nil && res != nil) ||
|
|
|
+ (a.results[j] != nil && res == nil) ||
|
|
|
+ a.results[j].Cmp(res) != 0 {
|
|
|
+ t.Errorf("#%d,%d Rounder got %v; expected %v", i, j, res, a.results[j])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+var decStringTests = []struct {
|
|
|
+ in string
|
|
|
+ out string
|
|
|
+ val int64
|
|
|
+ scale Scale // skip SetString if negative
|
|
|
+ ok bool
|
|
|
+ scanOk bool
|
|
|
+}{
|
|
|
+ {in: "", ok: false, scanOk: false},
|
|
|
+ {in: "a", ok: false, scanOk: false},
|
|
|
+ {in: "z", ok: false, scanOk: false},
|
|
|
+ {in: "+", ok: false, scanOk: false},
|
|
|
+ {in: "-", ok: false, scanOk: false},
|
|
|
+ {in: "g", ok: false, scanOk: false},
|
|
|
+ {in: ".", ok: false, scanOk: false},
|
|
|
+ {in: ".-0", ok: false, scanOk: false},
|
|
|
+ {in: ".+0", ok: false, scanOk: false},
|
|
|
+ // Scannable but not SetStringable
|
|
|
+ {"0b", "ignored", 0, 0, false, true},
|
|
|
+ {"0x", "ignored", 0, 0, false, true},
|
|
|
+ {"0xg", "ignored", 0, 0, false, true},
|
|
|
+ {"0.0g", "ignored", 0, 1, false, true},
|
|
|
+ // examples from godoc for Dec
|
|
|
+ {"0", "0", 0, 0, true, true},
|
|
|
+ {"0.00", "0.00", 0, 2, true, true},
|
|
|
+ {"ignored", "0", 0, -2, true, false},
|
|
|
+ {"1", "1", 1, 0, true, true},
|
|
|
+ {"1.00", "1.00", 100, 2, true, true},
|
|
|
+ {"10", "10", 10, 0, true, true},
|
|
|
+ {"ignored", "10", 1, -1, true, false},
|
|
|
+ // other tests
|
|
|
+ {"+0", "0", 0, 0, true, true},
|
|
|
+ {"-0", "0", 0, 0, true, true},
|
|
|
+ {"0.0", "0.0", 0, 1, true, true},
|
|
|
+ {"0.1", "0.1", 1, 1, true, true},
|
|
|
+ {"0.", "0", 0, 0, true, true},
|
|
|
+ {"-10", "-10", -1, -1, true, true},
|
|
|
+ {"-1", "-1", -1, 0, true, true},
|
|
|
+ {"-0.1", "-0.1", -1, 1, true, true},
|
|
|
+ {"-0.01", "-0.01", -1, 2, true, true},
|
|
|
+ {"+0.", "0", 0, 0, true, true},
|
|
|
+ {"-0.", "0", 0, 0, true, true},
|
|
|
+ {".0", "0.0", 0, 1, true, true},
|
|
|
+ {"+.0", "0.0", 0, 1, true, true},
|
|
|
+ {"-.0", "0.0", 0, 1, true, true},
|
|
|
+ {"0.0000000000", "0.0000000000", 0, 10, true, true},
|
|
|
+ {"0.0000000001", "0.0000000001", 1, 10, true, true},
|
|
|
+ {"-0.0000000000", "0.0000000000", 0, 10, true, true},
|
|
|
+ {"-0.0000000001", "-0.0000000001", -1, 10, true, true},
|
|
|
+ {"-10", "-10", -10, 0, true, true},
|
|
|
+ {"+10", "10", 10, 0, true, true},
|
|
|
+ {"00", "0", 0, 0, true, true},
|
|
|
+ {"023", "23", 23, 0, true, true}, // decimal, not octal
|
|
|
+ {"-02.3", "-2.3", -23, 1, true, true}, // decimal, not octal
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecGetString(t *testing.T) {
|
|
|
+ z := new(Dec)
|
|
|
+ for i, test := range decStringTests {
|
|
|
+ if !test.ok {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ z.SetUnscaled(big.NewInt(test.val))
|
|
|
+ z.SetScale(test.scale)
|
|
|
+
|
|
|
+ s := z.String()
|
|
|
+ if s != test.out {
|
|
|
+ t.Errorf("#%da got %s; want %s", i, s, test.out)
|
|
|
+ }
|
|
|
+
|
|
|
+ s = fmt.Sprintf("%d", z)
|
|
|
+ if s != test.out {
|
|
|
+ t.Errorf("#%db got %s; want %s", i, s, test.out)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecSetString(t *testing.T) {
|
|
|
+ tmp := new(Dec)
|
|
|
+ for i, test := range decStringTests {
|
|
|
+ if test.scale < 0 {
|
|
|
+ // SetString only supports scale >= 0
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // initialize to a non-zero value so that issues with parsing
|
|
|
+ // 0 are detected
|
|
|
+ tmp.Set(NewDecInt64(1234567890).SetScale(123))
|
|
|
+ n1, ok1 := new(Dec).SetString(test.in)
|
|
|
+ n2, ok2 := tmp.SetString(test.in)
|
|
|
+ expected := NewDecInt64(test.val).SetScale(test.scale)
|
|
|
+ if ok1 != test.ok || ok2 != test.ok {
|
|
|
+ t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if !ok1 {
|
|
|
+ if n1 != nil {
|
|
|
+ t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
|
|
|
+ }
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if !ok2 {
|
|
|
+ if n2 != nil {
|
|
|
+ t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
|
|
|
+ }
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if n1.Cmp(expected) != 0 {
|
|
|
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
|
|
|
+ }
|
|
|
+ if n2.Cmp(expected) != 0 {
|
|
|
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecScan(t *testing.T) {
|
|
|
+ tmp := new(Dec)
|
|
|
+ for i, test := range decStringTests {
|
|
|
+ if test.scale < 0 {
|
|
|
+ // SetString only supports scale >= 0
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // initialize to a non-zero value so that issues with parsing
|
|
|
+ // 0 are detected
|
|
|
+ tmp.Set(NewDecInt64(1234567890).SetScale(123))
|
|
|
+ n1, n2 := new(Dec), tmp
|
|
|
+ nn1, err1 := fmt.Sscan(test.in, n1)
|
|
|
+ nn2, err2 := fmt.Sscan(test.in, n2)
|
|
|
+ if !test.scanOk {
|
|
|
+ if err1 == nil || err2 == nil {
|
|
|
+ t.Errorf("#%d (input '%s') ok incorrect, should be %t", i, test.in, test.scanOk)
|
|
|
+ }
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ expected := NewDecInt64(test.val).SetScale(test.scale)
|
|
|
+ if nn1 != 1 || err1 != nil || nn2 != 1 || err2 != nil {
|
|
|
+ t.Errorf("#%d (input '%s') error %d %v, %d %v", i, test.in, nn1, err1, nn2, err2)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if n1.Cmp(expected) != 0 {
|
|
|
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
|
|
|
+ }
|
|
|
+ if n2.Cmp(expected) != 0 {
|
|
|
+ t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+var decScanNextTests = []struct {
|
|
|
+ in string
|
|
|
+ ok bool
|
|
|
+ next rune
|
|
|
+}{
|
|
|
+ {"", false, 0},
|
|
|
+ {"a", false, 'a'},
|
|
|
+ {"z", false, 'z'},
|
|
|
+ {"+", false, 0},
|
|
|
+ {"-", false, 0},
|
|
|
+ {"g", false, 'g'},
|
|
|
+ {".", false, 0},
|
|
|
+ {".-0", false, '-'},
|
|
|
+ {".+0", false, '+'},
|
|
|
+ {"0b", true, 'b'},
|
|
|
+ {"0x", true, 'x'},
|
|
|
+ {"0xg", true, 'x'},
|
|
|
+ {"0.0g", true, 'g'},
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecScanNext(t *testing.T) {
|
|
|
+ for i, test := range decScanNextTests {
|
|
|
+ rdr := strings.NewReader(test.in)
|
|
|
+ n1 := new(Dec)
|
|
|
+ nn1, _ := fmt.Fscan(rdr, n1)
|
|
|
+ if (test.ok && nn1 == 0) || (!test.ok && nn1 > 0) {
|
|
|
+ t.Errorf("#%d (input '%s') ok incorrect should be %t", i, test.in, test.ok)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ r := rune(0)
|
|
|
+ nn2, err := fmt.Fscanf(rdr, "%c", &r)
|
|
|
+ if test.next != r {
|
|
|
+ t.Errorf("#%d (input '%s') next incorrect, got %c should be %c, %d, %v", i, test.in, r, test.next, nn2, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+var decGobEncodingTests = []string{
|
|
|
+ "0",
|
|
|
+ "1",
|
|
|
+ "2",
|
|
|
+ "10",
|
|
|
+ "42",
|
|
|
+ "1234567890",
|
|
|
+ "298472983472983471903246121093472394872319615612417471234712061",
|
|
|
+}
|
|
|
+
|
|
|
+func TestDecGobEncoding(t *testing.T) {
|
|
|
+ var medium bytes.Buffer
|
|
|
+ enc := gob.NewEncoder(&medium)
|
|
|
+ dec := gob.NewDecoder(&medium)
|
|
|
+ for i, test := range decGobEncodingTests {
|
|
|
+ for j := 0; j < 2; j++ {
|
|
|
+ for k := Scale(-5); k <= 5; k++ {
|
|
|
+ medium.Reset() // empty buffer for each test case (in case of failures)
|
|
|
+ stest := test
|
|
|
+ if j != 0 {
|
|
|
+ // negative numbers
|
|
|
+ stest = "-" + test
|
|
|
+ }
|
|
|
+ var tx Dec
|
|
|
+ tx.SetString(stest)
|
|
|
+ tx.SetScale(k) // test with positive, negative, and zero scale
|
|
|
+ if err := enc.Encode(&tx); err != nil {
|
|
|
+ t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
|
|
|
+ }
|
|
|
+ var rx Dec
|
|
|
+ if err := dec.Decode(&rx); err != nil {
|
|
|
+ t.Errorf("#%d%c: decoding failed: %s", i, 'a'+j, err)
|
|
|
+ }
|
|
|
+ if rx.Cmp(&tx) != 0 {
|
|
|
+ t.Errorf("#%d%c: transmission failed: got %s want %s", i, 'a'+j, &rx, &tx)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|