|  | // Copyright 2015 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package big | 
|  |  | 
|  | import ( | 
|  | "bytes" | 
|  | "fmt" | 
|  | "testing" | 
|  | ) | 
|  |  | 
|  | var stringTests = []struct { | 
|  | in   string | 
|  | out  string | 
|  | base int | 
|  | val  int64 | 
|  | ok   bool | 
|  | }{ | 
|  | // invalid inputs | 
|  | {in: ""}, | 
|  | {in: "a"}, | 
|  | {in: "z"}, | 
|  | {in: "+"}, | 
|  | {in: "-"}, | 
|  | {in: "0b"}, | 
|  | {in: "0o"}, | 
|  | {in: "0x"}, | 
|  | {in: "0y"}, | 
|  | {in: "2", base: 2}, | 
|  | {in: "0b2", base: 0}, | 
|  | {in: "08"}, | 
|  | {in: "8", base: 8}, | 
|  | {in: "0xg", base: 0}, | 
|  | {in: "g", base: 16}, | 
|  |  | 
|  | // invalid inputs with separators | 
|  | // (smoke tests only - a comprehensive set of tests is in natconv_test.go) | 
|  | {in: "_"}, | 
|  | {in: "0_"}, | 
|  | {in: "_0"}, | 
|  | {in: "-1__0"}, | 
|  | {in: "0x10_"}, | 
|  | {in: "1_000", base: 10}, // separators are not permitted for bases != 0 | 
|  | {in: "d_e_a_d", base: 16}, | 
|  |  | 
|  | // valid inputs | 
|  | {"0", "0", 0, 0, true}, | 
|  | {"0", "0", 10, 0, true}, | 
|  | {"0", "0", 16, 0, true}, | 
|  | {"+0", "0", 0, 0, true}, | 
|  | {"-0", "0", 0, 0, true}, | 
|  | {"10", "10", 0, 10, true}, | 
|  | {"10", "10", 10, 10, true}, | 
|  | {"10", "10", 16, 16, true}, | 
|  | {"-10", "-10", 16, -16, true}, | 
|  | {"+10", "10", 16, 16, true}, | 
|  | {"0b10", "2", 0, 2, true}, | 
|  | {"0o10", "8", 0, 8, true}, | 
|  | {"0x10", "16", 0, 16, true}, | 
|  | {in: "0x10", base: 16}, | 
|  | {"-0x10", "-16", 0, -16, true}, | 
|  | {"+0x10", "16", 0, 16, true}, | 
|  | {"00", "0", 0, 0, true}, | 
|  | {"0", "0", 8, 0, true}, | 
|  | {"07", "7", 0, 7, true}, | 
|  | {"7", "7", 8, 7, true}, | 
|  | {"023", "19", 0, 19, true}, | 
|  | {"23", "23", 8, 19, true}, | 
|  | {"cafebabe", "cafebabe", 16, 0xcafebabe, true}, | 
|  | {"0b0", "0", 0, 0, true}, | 
|  | {"-111", "-111", 2, -7, true}, | 
|  | {"-0b111", "-7", 0, -7, true}, | 
|  | {"0b1001010111", "599", 0, 0x257, true}, | 
|  | {"1001010111", "1001010111", 2, 0x257, true}, | 
|  | {"A", "a", 36, 10, true}, | 
|  | {"A", "A", 37, 36, true}, | 
|  | {"ABCXYZ", "abcxyz", 36, 623741435, true}, | 
|  | {"ABCXYZ", "ABCXYZ", 62, 33536793425, true}, | 
|  |  | 
|  | // valid input with separators | 
|  | // (smoke tests only - a comprehensive set of tests is in natconv_test.go) | 
|  | {"1_000", "1000", 0, 1000, true}, | 
|  | {"0b_1010", "10", 0, 10, true}, | 
|  | {"+0o_660", "432", 0, 0660, true}, | 
|  | {"-0xF00D_1E", "-15731998", 0, -0xf00d1e, true}, | 
|  | } | 
|  |  | 
|  | func TestIntText(t *testing.T) { | 
|  | z := new(Int) | 
|  | for _, test := range stringTests { | 
|  | if !test.ok { | 
|  | continue | 
|  | } | 
|  |  | 
|  | _, ok := z.SetString(test.in, test.base) | 
|  | if !ok { | 
|  | t.Errorf("%v: failed to parse", test) | 
|  | continue | 
|  | } | 
|  |  | 
|  | base := test.base | 
|  | if base == 0 { | 
|  | base = 10 | 
|  | } | 
|  |  | 
|  | if got := z.Text(base); got != test.out { | 
|  | t.Errorf("%v: got %s; want %s", test, got, test.out) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestAppendText(t *testing.T) { | 
|  | z := new(Int) | 
|  | var buf []byte | 
|  | for _, test := range stringTests { | 
|  | if !test.ok { | 
|  | continue | 
|  | } | 
|  |  | 
|  | _, ok := z.SetString(test.in, test.base) | 
|  | if !ok { | 
|  | t.Errorf("%v: failed to parse", test) | 
|  | continue | 
|  | } | 
|  |  | 
|  | base := test.base | 
|  | if base == 0 { | 
|  | base = 10 | 
|  | } | 
|  |  | 
|  | i := len(buf) | 
|  | buf = z.Append(buf, base) | 
|  | if got := string(buf[i:]); got != test.out { | 
|  | t.Errorf("%v: got %s; want %s", test, got, test.out) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func format(base int) string { | 
|  | switch base { | 
|  | case 2: | 
|  | return "%b" | 
|  | case 8: | 
|  | return "%o" | 
|  | case 16: | 
|  | return "%x" | 
|  | } | 
|  | return "%d" | 
|  | } | 
|  |  | 
|  | func TestGetString(t *testing.T) { | 
|  | z := new(Int) | 
|  | for i, test := range stringTests { | 
|  | if !test.ok { | 
|  | continue | 
|  | } | 
|  | z.SetInt64(test.val) | 
|  |  | 
|  | if test.base == 10 { | 
|  | if got := z.String(); got != test.out { | 
|  | t.Errorf("#%da got %s; want %s", i, got, test.out) | 
|  | } | 
|  | } | 
|  |  | 
|  | f := format(test.base) | 
|  | got := fmt.Sprintf(f, z) | 
|  | if f == "%d" { | 
|  | if got != fmt.Sprintf("%d", test.val) { | 
|  | t.Errorf("#%db got %s; want %d", i, got, test.val) | 
|  | } | 
|  | } else { | 
|  | if got != test.out { | 
|  | t.Errorf("#%dc got %s; want %s", i, got, test.out) | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func TestSetString(t *testing.T) { | 
|  | tmp := new(Int) | 
|  | for i, test := range stringTests { | 
|  | // initialize to a non-zero value so that issues with parsing | 
|  | // 0 are detected | 
|  | tmp.SetInt64(1234567890) | 
|  | n1, ok1 := new(Int).SetString(test.in, test.base) | 
|  | n2, ok2 := tmp.SetString(test.in, test.base) | 
|  | expected := NewInt(test.val) | 
|  | 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 ok1 && !isNormalized(n1) { | 
|  | t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1) | 
|  | } | 
|  | if ok2 && !isNormalized(n2) { | 
|  | t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2) | 
|  | } | 
|  |  | 
|  | 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 formatTests = []struct { | 
|  | input  string | 
|  | format string | 
|  | output string | 
|  | }{ | 
|  | {"<nil>", "%x", "<nil>"}, | 
|  | {"<nil>", "%#x", "<nil>"}, | 
|  | {"<nil>", "%#y", "%!y(big.Int=<nil>)"}, | 
|  |  | 
|  | {"10", "%b", "1010"}, | 
|  | {"10", "%o", "12"}, | 
|  | {"10", "%d", "10"}, | 
|  | {"10", "%v", "10"}, | 
|  | {"10", "%x", "a"}, | 
|  | {"10", "%X", "A"}, | 
|  | {"-10", "%X", "-A"}, | 
|  | {"10", "%y", "%!y(big.Int=10)"}, | 
|  | {"-10", "%y", "%!y(big.Int=-10)"}, | 
|  |  | 
|  | {"10", "%#b", "0b1010"}, | 
|  | {"10", "%#o", "012"}, | 
|  | {"10", "%O", "0o12"}, | 
|  | {"-10", "%#b", "-0b1010"}, | 
|  | {"-10", "%#o", "-012"}, | 
|  | {"-10", "%O", "-0o12"}, | 
|  | {"10", "%#d", "10"}, | 
|  | {"10", "%#v", "10"}, | 
|  | {"10", "%#x", "0xa"}, | 
|  | {"10", "%#X", "0XA"}, | 
|  | {"-10", "%#X", "-0XA"}, | 
|  | {"10", "%#y", "%!y(big.Int=10)"}, | 
|  | {"-10", "%#y", "%!y(big.Int=-10)"}, | 
|  |  | 
|  | {"1234", "%d", "1234"}, | 
|  | {"1234", "%3d", "1234"}, | 
|  | {"1234", "%4d", "1234"}, | 
|  | {"-1234", "%d", "-1234"}, | 
|  | {"1234", "% 5d", " 1234"}, | 
|  | {"1234", "%+5d", "+1234"}, | 
|  | {"1234", "%-5d", "1234 "}, | 
|  | {"1234", "%x", "4d2"}, | 
|  | {"1234", "%X", "4D2"}, | 
|  | {"-1234", "%3x", "-4d2"}, | 
|  | {"-1234", "%4x", "-4d2"}, | 
|  | {"-1234", "%5x", " -4d2"}, | 
|  | {"-1234", "%-5x", "-4d2 "}, | 
|  | {"1234", "%03d", "1234"}, | 
|  | {"1234", "%04d", "1234"}, | 
|  | {"1234", "%05d", "01234"}, | 
|  | {"1234", "%06d", "001234"}, | 
|  | {"-1234", "%06d", "-01234"}, | 
|  | {"1234", "%+06d", "+01234"}, | 
|  | {"1234", "% 06d", " 01234"}, | 
|  | {"1234", "%-6d", "1234  "}, | 
|  | {"1234", "%-06d", "1234  "}, | 
|  | {"-1234", "%-06d", "-1234 "}, | 
|  |  | 
|  | {"1234", "%.3d", "1234"}, | 
|  | {"1234", "%.4d", "1234"}, | 
|  | {"1234", "%.5d", "01234"}, | 
|  | {"1234", "%.6d", "001234"}, | 
|  | {"-1234", "%.3d", "-1234"}, | 
|  | {"-1234", "%.4d", "-1234"}, | 
|  | {"-1234", "%.5d", "-01234"}, | 
|  | {"-1234", "%.6d", "-001234"}, | 
|  |  | 
|  | {"1234", "%8.3d", "    1234"}, | 
|  | {"1234", "%8.4d", "    1234"}, | 
|  | {"1234", "%8.5d", "   01234"}, | 
|  | {"1234", "%8.6d", "  001234"}, | 
|  | {"-1234", "%8.3d", "   -1234"}, | 
|  | {"-1234", "%8.4d", "   -1234"}, | 
|  | {"-1234", "%8.5d", "  -01234"}, | 
|  | {"-1234", "%8.6d", " -001234"}, | 
|  |  | 
|  | {"1234", "%+8.3d", "   +1234"}, | 
|  | {"1234", "%+8.4d", "   +1234"}, | 
|  | {"1234", "%+8.5d", "  +01234"}, | 
|  | {"1234", "%+8.6d", " +001234"}, | 
|  | {"-1234", "%+8.3d", "   -1234"}, | 
|  | {"-1234", "%+8.4d", "   -1234"}, | 
|  | {"-1234", "%+8.5d", "  -01234"}, | 
|  | {"-1234", "%+8.6d", " -001234"}, | 
|  |  | 
|  | {"1234", "% 8.3d", "    1234"}, | 
|  | {"1234", "% 8.4d", "    1234"}, | 
|  | {"1234", "% 8.5d", "   01234"}, | 
|  | {"1234", "% 8.6d", "  001234"}, | 
|  | {"-1234", "% 8.3d", "   -1234"}, | 
|  | {"-1234", "% 8.4d", "   -1234"}, | 
|  | {"-1234", "% 8.5d", "  -01234"}, | 
|  | {"-1234", "% 8.6d", " -001234"}, | 
|  |  | 
|  | {"1234", "%.3x", "4d2"}, | 
|  | {"1234", "%.4x", "04d2"}, | 
|  | {"1234", "%.5x", "004d2"}, | 
|  | {"1234", "%.6x", "0004d2"}, | 
|  | {"-1234", "%.3x", "-4d2"}, | 
|  | {"-1234", "%.4x", "-04d2"}, | 
|  | {"-1234", "%.5x", "-004d2"}, | 
|  | {"-1234", "%.6x", "-0004d2"}, | 
|  |  | 
|  | {"1234", "%8.3x", "     4d2"}, | 
|  | {"1234", "%8.4x", "    04d2"}, | 
|  | {"1234", "%8.5x", "   004d2"}, | 
|  | {"1234", "%8.6x", "  0004d2"}, | 
|  | {"-1234", "%8.3x", "    -4d2"}, | 
|  | {"-1234", "%8.4x", "   -04d2"}, | 
|  | {"-1234", "%8.5x", "  -004d2"}, | 
|  | {"-1234", "%8.6x", " -0004d2"}, | 
|  |  | 
|  | {"1234", "%+8.3x", "    +4d2"}, | 
|  | {"1234", "%+8.4x", "   +04d2"}, | 
|  | {"1234", "%+8.5x", "  +004d2"}, | 
|  | {"1234", "%+8.6x", " +0004d2"}, | 
|  | {"-1234", "%+8.3x", "    -4d2"}, | 
|  | {"-1234", "%+8.4x", "   -04d2"}, | 
|  | {"-1234", "%+8.5x", "  -004d2"}, | 
|  | {"-1234", "%+8.6x", " -0004d2"}, | 
|  |  | 
|  | {"1234", "% 8.3x", "     4d2"}, | 
|  | {"1234", "% 8.4x", "    04d2"}, | 
|  | {"1234", "% 8.5x", "   004d2"}, | 
|  | {"1234", "% 8.6x", "  0004d2"}, | 
|  | {"1234", "% 8.7x", " 00004d2"}, | 
|  | {"1234", "% 8.8x", " 000004d2"}, | 
|  | {"-1234", "% 8.3x", "    -4d2"}, | 
|  | {"-1234", "% 8.4x", "   -04d2"}, | 
|  | {"-1234", "% 8.5x", "  -004d2"}, | 
|  | {"-1234", "% 8.6x", " -0004d2"}, | 
|  | {"-1234", "% 8.7x", "-00004d2"}, | 
|  | {"-1234", "% 8.8x", "-000004d2"}, | 
|  |  | 
|  | {"1234", "%-8.3d", "1234    "}, | 
|  | {"1234", "%-8.4d", "1234    "}, | 
|  | {"1234", "%-8.5d", "01234   "}, | 
|  | {"1234", "%-8.6d", "001234  "}, | 
|  | {"1234", "%-8.7d", "0001234 "}, | 
|  | {"1234", "%-8.8d", "00001234"}, | 
|  | {"-1234", "%-8.3d", "-1234   "}, | 
|  | {"-1234", "%-8.4d", "-1234   "}, | 
|  | {"-1234", "%-8.5d", "-01234  "}, | 
|  | {"-1234", "%-8.6d", "-001234 "}, | 
|  | {"-1234", "%-8.7d", "-0001234"}, | 
|  | {"-1234", "%-8.8d", "-00001234"}, | 
|  |  | 
|  | {"16777215", "%b", "111111111111111111111111"}, // 2**24 - 1 | 
|  |  | 
|  | {"0", "%.d", ""}, | 
|  | {"0", "%.0d", ""}, | 
|  | {"0", "%3.d", ""}, | 
|  | } | 
|  |  | 
|  | func TestFormat(t *testing.T) { | 
|  | for i, test := range formatTests { | 
|  | var x *Int | 
|  | if test.input != "<nil>" { | 
|  | var ok bool | 
|  | x, ok = new(Int).SetString(test.input, 0) | 
|  | if !ok { | 
|  | t.Errorf("#%d failed reading input %s", i, test.input) | 
|  | } | 
|  | } | 
|  | output := fmt.Sprintf(test.format, x) | 
|  | if output != test.output { | 
|  | t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | var scanTests = []struct { | 
|  | input     string | 
|  | format    string | 
|  | output    string | 
|  | remaining int | 
|  | }{ | 
|  | {"1010", "%b", "10", 0}, | 
|  | {"0b1010", "%v", "10", 0}, | 
|  | {"12", "%o", "10", 0}, | 
|  | {"012", "%v", "10", 0}, | 
|  | {"10", "%d", "10", 0}, | 
|  | {"10", "%v", "10", 0}, | 
|  | {"a", "%x", "10", 0}, | 
|  | {"0xa", "%v", "10", 0}, | 
|  | {"A", "%X", "10", 0}, | 
|  | {"-A", "%X", "-10", 0}, | 
|  | {"+0b1011001", "%v", "89", 0}, | 
|  | {"0xA", "%v", "10", 0}, | 
|  | {"0 ", "%v", "0", 1}, | 
|  | {"2+3", "%v", "2", 2}, | 
|  | {"0XABC 12", "%v", "2748", 3}, | 
|  | } | 
|  |  | 
|  | func TestScan(t *testing.T) { | 
|  | var buf bytes.Buffer | 
|  | for i, test := range scanTests { | 
|  | x := new(Int) | 
|  | buf.Reset() | 
|  | buf.WriteString(test.input) | 
|  | if _, err := fmt.Fscanf(&buf, test.format, x); err != nil { | 
|  | t.Errorf("#%d error: %s", i, err) | 
|  | } | 
|  | if x.String() != test.output { | 
|  | t.Errorf("#%d got %s; want %s", i, x.String(), test.output) | 
|  | } | 
|  | if buf.Len() != test.remaining { | 
|  | t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining) | 
|  | } | 
|  | } | 
|  | } |