Source file src/strconv/atoc_test.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package strconv_test
     6  
     7  import (
     8  	"math"
     9  	"math/cmplx"
    10  	"reflect"
    11  	. "strconv"
    12  	"testing"
    13  )
    14  
    15  var (
    16  	infp0 = complex(math.Inf(+1), 0)
    17  	infm0 = complex(math.Inf(-1), 0)
    18  	inf0p = complex(0, math.Inf(+1))
    19  	inf0m = complex(0, math.Inf(-1))
    20  
    21  	infpp = complex(math.Inf(+1), math.Inf(+1))
    22  	infpm = complex(math.Inf(+1), math.Inf(-1))
    23  	infmp = complex(math.Inf(-1), math.Inf(+1))
    24  	infmm = complex(math.Inf(-1), math.Inf(-1))
    25  )
    26  
    27  type atocTest struct {
    28  	in  string
    29  	out complex128
    30  	err error
    31  }
    32  
    33  func TestParseComplex(t *testing.T) {
    34  	tests := []atocTest{
    35  		// Clearly invalid
    36  		{"", 0, ErrSyntax},
    37  		{" ", 0, ErrSyntax},
    38  		{"(", 0, ErrSyntax},
    39  		{")", 0, ErrSyntax},
    40  		{"i", 0, ErrSyntax},
    41  		{"+i", 0, ErrSyntax},
    42  		{"-i", 0, ErrSyntax},
    43  		{"1I", 0, ErrSyntax},
    44  		{"10  + 5i", 0, ErrSyntax},
    45  		{"3+", 0, ErrSyntax},
    46  		{"3+5", 0, ErrSyntax},
    47  		{"3+5+5i", 0, ErrSyntax},
    48  
    49  		// Parentheses
    50  		{"()", 0, ErrSyntax},
    51  		{"(i)", 0, ErrSyntax},
    52  		{"(0)", 0, nil},
    53  		{"(1i)", 1i, nil},
    54  		{"(3.0+5.5i)", 3.0 + 5.5i, nil},
    55  		{"(1)+1i", 0, ErrSyntax},
    56  		{"(3.0+5.5i", 0, ErrSyntax},
    57  		{"3.0+5.5i)", 0, ErrSyntax},
    58  
    59  		// NaNs
    60  		{"NaN", complex(math.NaN(), 0), nil},
    61  		{"NANi", complex(0, math.NaN()), nil},
    62  		{"nan+nAni", complex(math.NaN(), math.NaN()), nil},
    63  		{"+NaN", 0, ErrSyntax},
    64  		{"-NaN", 0, ErrSyntax},
    65  		{"NaN-NaNi", 0, ErrSyntax},
    66  
    67  		// Infs
    68  		{"Inf", infp0, nil},
    69  		{"+inf", infp0, nil},
    70  		{"-inf", infm0, nil},
    71  		{"Infinity", infp0, nil},
    72  		{"+INFINITY", infp0, nil},
    73  		{"-infinity", infm0, nil},
    74  		{"+infi", inf0p, nil},
    75  		{"0-infinityi", inf0m, nil},
    76  		{"Inf+Infi", infpp, nil},
    77  		{"+Inf-Infi", infpm, nil},
    78  		{"-Infinity+Infi", infmp, nil},
    79  		{"inf-inf", 0, ErrSyntax},
    80  
    81  		// Zeros
    82  		{"0", 0, nil},
    83  		{"0i", 0, nil},
    84  		{"-0.0i", 0, nil},
    85  		{"0+0.0i", 0, nil},
    86  		{"0e+0i", 0, nil},
    87  		{"0e-0+0i", 0, nil},
    88  		{"-0.0-0.0i", 0, nil},
    89  		{"0e+012345", 0, nil},
    90  		{"0x0p+012345i", 0, nil},
    91  		{"0x0.00p-012345i", 0, nil},
    92  		{"+0e-0+0e-0i", 0, nil},
    93  		{"0e+0+0e+0i", 0, nil},
    94  		{"-0e+0-0e+0i", 0, nil},
    95  
    96  		// Regular non-zeroes
    97  		{"0.1", 0.1, nil},
    98  		{"0.1i", 0 + 0.1i, nil},
    99  		{"0.123", 0.123, nil},
   100  		{"0.123i", 0 + 0.123i, nil},
   101  		{"0.123+0.123i", 0.123 + 0.123i, nil},
   102  		{"99", 99, nil},
   103  		{"+99", 99, nil},
   104  		{"-99", -99, nil},
   105  		{"+1i", 1i, nil},
   106  		{"-1i", -1i, nil},
   107  		{"+3+1i", 3 + 1i, nil},
   108  		{"30+3i", 30 + 3i, nil},
   109  		{"+3e+3-3e+3i", 3e+3 - 3e+3i, nil},
   110  		{"+3e+3+3e+3i", 3e+3 + 3e+3i, nil},
   111  		{"+3e+3+3e+3i+", 0, ErrSyntax},
   112  
   113  		// Separators
   114  		{"0.1", 0.1, nil},
   115  		{"0.1i", 0 + 0.1i, nil},
   116  		{"0.1_2_3", 0.123, nil},
   117  		{"+0x_3p3i", 0x3p3i, nil},
   118  		{"0_0+0x_0p0i", 0, nil},
   119  		{"0x_10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil},
   120  		{"+0x_1_0.3p-8+0x_3_0p3i", 0x10.3p-8 + 0x30p3i, nil},
   121  		{"0x1_0.3p+8-0x_3p3i", 0x10.3p+8 - 0x3p3i, nil},
   122  
   123  		// Hexadecimals
   124  		{"0x10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil},
   125  		{"+0x10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil},
   126  		{"0x10.3p+8-0x3p3i", 0x10.3p+8 - 0x3p3i, nil},
   127  		{"0x1p0", 1, nil},
   128  		{"0x1p1", 2, nil},
   129  		{"0x1p-1", 0.5, nil},
   130  		{"0x1ep-1", 15, nil},
   131  		{"-0x1ep-1", -15, nil},
   132  		{"-0x2p3", -16, nil},
   133  		{"0x1e2", 0, ErrSyntax},
   134  		{"1p2", 0, ErrSyntax},
   135  		{"0x1e2i", 0, ErrSyntax},
   136  
   137  		// ErrRange
   138  		// next float64 - too large
   139  		{"+0x1p1024", infp0, ErrRange},
   140  		{"-0x1p1024", infm0, ErrRange},
   141  		{"+0x1p1024i", inf0p, ErrRange},
   142  		{"-0x1p1024i", inf0m, ErrRange},
   143  		{"+0x1p1024+0x1p1024i", infpp, ErrRange},
   144  		{"+0x1p1024-0x1p1024i", infpm, ErrRange},
   145  		{"-0x1p1024+0x1p1024i", infmp, ErrRange},
   146  		{"-0x1p1024-0x1p1024i", infmm, ErrRange},
   147  		// the border is ...158079
   148  		// borderline - okay
   149  		{"+0x1.fffffffffffff7fffp1023+0x1.fffffffffffff7fffp1023i", 1.7976931348623157e+308 + 1.7976931348623157e+308i, nil},
   150  		{"+0x1.fffffffffffff7fffp1023-0x1.fffffffffffff7fffp1023i", 1.7976931348623157e+308 - 1.7976931348623157e+308i, nil},
   151  		{"-0x1.fffffffffffff7fffp1023+0x1.fffffffffffff7fffp1023i", -1.7976931348623157e+308 + 1.7976931348623157e+308i, nil},
   152  		{"-0x1.fffffffffffff7fffp1023-0x1.fffffffffffff7fffp1023i", -1.7976931348623157e+308 - 1.7976931348623157e+308i, nil},
   153  		// borderline - too large
   154  		{"+0x1.fffffffffffff8p1023", infp0, ErrRange},
   155  		{"-0x1fffffffffffff.8p+971", infm0, ErrRange},
   156  		{"+0x1.fffffffffffff8p1023i", inf0p, ErrRange},
   157  		{"-0x1fffffffffffff.8p+971i", inf0m, ErrRange},
   158  		{"+0x1.fffffffffffff8p1023+0x1.fffffffffffff8p1023i", infpp, ErrRange},
   159  		{"+0x1.fffffffffffff8p1023-0x1.fffffffffffff8p1023i", infpm, ErrRange},
   160  		{"-0x1fffffffffffff.8p+971+0x1fffffffffffff.8p+971i", infmp, ErrRange},
   161  		{"-0x1fffffffffffff8p+967-0x1fffffffffffff8p+967i", infmm, ErrRange},
   162  		// a little too large
   163  		{"1e308+1e308i", 1e+308 + 1e+308i, nil},
   164  		{"2e308+2e308i", infpp, ErrRange},
   165  		{"1e309+1e309i", infpp, ErrRange},
   166  		{"0x1p1025+0x1p1025i", infpp, ErrRange},
   167  		{"2e308", infp0, ErrRange},
   168  		{"1e309", infp0, ErrRange},
   169  		{"0x1p1025", infp0, ErrRange},
   170  		{"2e308i", inf0p, ErrRange},
   171  		{"1e309i", inf0p, ErrRange},
   172  		{"0x1p1025i", inf0p, ErrRange},
   173  		// way too large
   174  		{"+1e310+1e310i", infpp, ErrRange},
   175  		{"+1e310-1e310i", infpm, ErrRange},
   176  		{"-1e310+1e310i", infmp, ErrRange},
   177  		{"-1e310-1e310i", infmm, ErrRange},
   178  		// under/overflow exponent
   179  		{"1e-4294967296", 0, nil},
   180  		{"1e-4294967296i", 0, nil},
   181  		{"1e-4294967296+1i", 1i, nil},
   182  		{"1+1e-4294967296i", 1, nil},
   183  		{"1e-4294967296+1e-4294967296i", 0, nil},
   184  		{"1e+4294967296", infp0, ErrRange},
   185  		{"1e+4294967296i", inf0p, ErrRange},
   186  		{"1e+4294967296+1e+4294967296i", infpp, ErrRange},
   187  		{"1e+4294967296-1e+4294967296i", infpm, ErrRange},
   188  	}
   189  	for i := range tests {
   190  		test := &tests[i]
   191  		if test.err != nil {
   192  			test.err = &NumError{Func: "ParseComplex", Num: test.in, Err: test.err}
   193  		}
   194  		got, err := ParseComplex(test.in, 128)
   195  		if !reflect.DeepEqual(err, test.err) {
   196  			t.Fatalf("ParseComplex(%q, 128) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
   197  		}
   198  		if !(cmplx.IsNaN(test.out) && cmplx.IsNaN(got)) && got != test.out {
   199  			t.Fatalf("ParseComplex(%q, 128) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
   200  		}
   201  
   202  		if complex128(complex64(test.out)) == test.out {
   203  			got, err := ParseComplex(test.in, 64)
   204  			if !reflect.DeepEqual(err, test.err) {
   205  				t.Fatalf("ParseComplex(%q, 64) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
   206  			}
   207  			got64 := complex64(got)
   208  			if complex128(got64) != test.out {
   209  				t.Fatalf("ParseComplex(%q, 64) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err)
   210  			}
   211  		}
   212  	}
   213  }
   214  
   215  // Issue 42297: allow ParseComplex(s, not_32_or_64) for legacy reasons
   216  func TestParseComplexIncorrectBitSize(t *testing.T) {
   217  	const s = "1.5e308+1.0e307i"
   218  	const want = 1.5e308 + 1.0e307i
   219  
   220  	for _, bitSize := range []int{0, 10, 100, 256} {
   221  		c, err := ParseComplex(s, bitSize)
   222  		if err != nil {
   223  			t.Fatalf("ParseComplex(%q, %d) gave error %s", s, bitSize, err)
   224  		}
   225  		if c != want {
   226  			t.Fatalf("ParseComplex(%q, %d) = %g (expected %g)", s, bitSize, c, want)
   227  		}
   228  	}
   229  }
   230  

View as plain text