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 }