cuelang.org/go@v0.10.1/cue/literal/num_test.go (about)

     1  // Copyright 2020 CUE Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package literal
    16  
    17  import (
    18  	"fmt"
    19  	"math/big"
    20  	"strconv"
    21  	"testing"
    22  
    23  	"cuelang.org/go/cue/token"
    24  	"github.com/google/go-cmp/cmp"
    25  	"github.com/google/go-cmp/cmp/cmpopts"
    26  )
    27  
    28  func mkInt(i int) NumInfo {
    29  	return NumInfo{
    30  		base: 10,
    31  		neg:  i < 0,
    32  		buf:  []byte(strconv.Itoa(i)),
    33  	}
    34  }
    35  
    36  func mkFloat(a string) NumInfo {
    37  	return NumInfo{
    38  		base:    10,
    39  		buf:     []byte(a),
    40  		neg:     a[0] == '-',
    41  		isFloat: true,
    42  	}
    43  }
    44  
    45  func mkMul(i string, m Multiplier, base byte) NumInfo {
    46  	return NumInfo{
    47  		base: base,
    48  		mul:  m,
    49  		neg:  i[0] == '-',
    50  		buf:  []byte(i),
    51  	}
    52  }
    53  
    54  func TestNumbers(t *testing.T) {
    55  	// hk := newInt(testBase, newRepresentation(0, 10, true)).setInt64(100000)
    56  	testCases := []struct {
    57  		lit  string
    58  		norm string
    59  		n    NumInfo
    60  	}{
    61  		{"0", "0", mkInt(0)},
    62  		{"1", "1", mkInt(1)},
    63  		{"+1", "1", mkInt(1)},
    64  		{"-1", "-1", mkInt(-1)},
    65  		{"100_000", "100000", NumInfo{UseSep: true, base: 10, buf: []byte("100000")}},
    66  		{"1.", "1.", mkFloat("1.")},
    67  		{"0.", "0.", mkFloat("0.")},
    68  		{".0", "0.0", mkFloat("0.0")},
    69  		{"012.34", "12.34", mkFloat("12.34")},
    70  		{".01", "0.01", mkFloat("0.01")},
    71  		{".01e2", "0.01e2", mkFloat("0.01e2")},
    72  		{"0.", "0.", mkFloat("0.")},
    73  		{"1K", "1000", mkMul("1", K, 10)},
    74  		{".5K", "500", mkMul("0.5", K, 10)},
    75  		{"1Mi", "1048576", mkMul("1", Mi, 10)},
    76  		{"1.5Mi", "1572864", mkMul("1.5", Mi, 10)},
    77  		// {"1.3Mi", &bottom{}}, // Cannot be accurately represented.
    78  		{"1.3G", "1300000000", mkMul("1.3", G, 10)},
    79  		{"1.3e+20", "1.3e+20", mkFloat("1.3e+20")},
    80  		{"1.3e20", "1.3e20", mkFloat("1.3e20")},
    81  		{"1.3e-5", "1.3e-5", mkFloat("1.3e-5")},
    82  		{".3e-1", "0.3e-1", mkFloat("0.3e-1")},
    83  		{"0e-5", "0e-5", mkFloat("0e-5")},
    84  		{"0E-5", "0e-5", mkFloat("0e-5")},
    85  		{"5e-5", "5e-5", mkFloat("5e-5")},
    86  		{"5E-5", "5e-5", mkFloat("5e-5")},
    87  		{"0x1234", "4660", mkMul("1234", 0, 16)},
    88  		{"0xABCD", "43981", mkMul("ABCD", 0, 16)},
    89  		{"-0xABCD", "-43981", mkMul("-ABCD", 0, 16)},
    90  		{"0b11001000", "200", mkMul("11001000", 0, 2)},
    91  		{"0b1", "1", mkMul("1", 0, 2)},
    92  		{"0o755", "493", mkMul("755", 0, 8)},
    93  		{"0755", "493", mkMul("755", 0, 8)},
    94  	}
    95  	n := NumInfo{}
    96  	for i, tc := range testCases {
    97  		t.Run(fmt.Sprintf("%d/%+q", i, tc.lit), func(t *testing.T) {
    98  			if err := ParseNum(tc.lit, &n); err != nil {
    99  				t.Fatal(err)
   100  			}
   101  			n.src = ""
   102  			n.p = 0
   103  			n.ch = 0
   104  			if diff := cmp.Diff(n, tc.n, diffOpts...); diff != "" {
   105  				t.Error(diff)
   106  				t.Errorf("%#v, %#v\n", n, tc.n)
   107  			}
   108  			if n.String() != tc.norm {
   109  				t.Errorf("got %v; want %v", n.String(), tc.norm)
   110  			}
   111  		})
   112  	}
   113  }
   114  
   115  var diffOpts = []cmp.Option{
   116  	cmp.Comparer(func(x, y big.Rat) bool {
   117  		return x.String() == y.String()
   118  	}),
   119  	cmp.Comparer(func(x, y big.Int) bool {
   120  		return x.String() == y.String()
   121  	}),
   122  	cmp.AllowUnexported(
   123  		NumInfo{},
   124  	),
   125  	cmpopts.IgnoreUnexported(
   126  		token.Pos{},
   127  	),
   128  	cmpopts.EquateEmpty(),
   129  }
   130  
   131  func TestNumErrors(t *testing.T) {
   132  	testCases := []string{
   133  		`0x`,
   134  		`0o`,
   135  		`0b`,
   136  		`0_`,
   137  		"0128",
   138  		"e+100",
   139  		".p",
   140  		``,
   141  		`"`,
   142  		`"a`,
   143  		`23.34e`,
   144  		`23.34e33pp`,
   145  	}
   146  	for _, tc := range testCases {
   147  		t.Run(fmt.Sprintf("%+q", tc), func(t *testing.T) {
   148  			n := &NumInfo{}
   149  			err := ParseNum(tc, n)
   150  			if err == nil {
   151  				t.Fatalf("expected error but found none")
   152  			}
   153  		})
   154  	}
   155  }