github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/eval/vals/conversion_test.go (about) 1 package vals 2 3 import ( 4 "math/big" 5 "reflect" 6 "testing" 7 8 . "src.elv.sh/pkg/tt" 9 ) 10 11 type someType struct { 12 foo string 13 } 14 15 // A wrapper around ScanToGo, to make it easier to test. Instead of supplying a 16 // pointer to the destination, an initial value to the destination is supplied 17 // and the result is returned. 18 func scanToGo2(src interface{}, dstInit interface{}) (interface{}, error) { 19 ptr := reflect.New(TypeOf(dstInit)) 20 err := ScanToGo(src, ptr.Interface()) 21 return ptr.Elem().Interface(), err 22 } 23 24 func TestScanToGo(t *testing.T) { 25 Test(t, Fn("ScanToGo", scanToGo2), Table{ 26 // int 27 Args("12", 0).Rets(12), 28 Args("0x12", 0).Rets(0x12), 29 Args(12.0, 0).Rets(0, errMustBeInteger), 30 Args(0.5, 0).Rets(0, errMustBeInteger), 31 Args(someType{}, 0).Rets(Any, errMustBeInteger), 32 Args("x", 0).Rets(Any, cannotParseAs{"integer", "x"}), 33 34 // float64 35 Args(23, 0.0).Rets(23.0), 36 Args(big.NewRat(1, 2), 0.0).Rets(0.5), 37 Args(1.2, 0.0).Rets(1.2), 38 Args("23", 0.0).Rets(23.0), 39 Args("0x23", 0.0).Rets(float64(0x23)), 40 Args(someType{}, 0.0).Rets(Any, errMustBeNumber), 41 Args("x", 0.0).Rets(Any, cannotParseAs{"number", "x"}), 42 43 // Num is tested below 44 45 // rune 46 Args("x", ' ').Rets('x'), 47 Args(someType{}, ' ').Rets(Any, errMustBeString), 48 Args("\xc3\x28", ' ').Rets(Any, errMustBeValidUTF8), // Invalid UTF8 49 Args("ab", ' ').Rets(Any, errMustHaveSingleRune), 50 51 // Other types don't undergo any conversion, as long as the types match 52 Args("foo", "").Rets("foo"), 53 Args(someType{"foo"}, someType{}).Rets(someType{"foo"}), 54 Args(nil, nil).Rets(nil), 55 Args("x", someType{}).Rets(Any, wrongType{"!!vals.someType", "string"}), 56 }) 57 } 58 59 func scanToGoNum(src interface{}) (Num, error) { 60 var n Num 61 err := ScanToGo(src, &n) 62 return n, err 63 } 64 65 func TestScanToGoNum(t *testing.T) { 66 Test(t, Fn("ScanToGo", scanToGoNum), Table{ 67 // Strings are automatically converted 68 Args("12").Rets(12), 69 Args(z).Rets(bigInt(z)), 70 Args("1/2").Rets(big.NewRat(1, 2)), 71 Args("12.0").Rets(12.0), 72 // Already numbers 73 Args(12).Rets(12), 74 Args(bigInt(z)).Rets(bigInt(z)), 75 Args(big.NewRat(1, 2)).Rets(big.NewRat(1, 2)), 76 Args(12.0).Rets(12.0), 77 }) 78 } 79 80 func TestFromGo(t *testing.T) { 81 Test(t, Fn("FromGo", FromGo), Table{ 82 // BigInt -> int, when in range 83 Args(bigInt(z)).Rets(bigInt(z)), 84 Args(big.NewInt(100)).Rets(100), 85 // BigRat -> BigInt or int, when denominator is 1 86 Args(bigRat(z1 + "/" + z)).Rets(bigRat(z1 + "/" + z)), 87 Args(bigRat(z + "/1")).Rets(bigInt(z)), 88 Args(bigRat("2/1")).Rets(2), 89 // rune -> string 90 Args('x').Rets("x"), 91 92 // Other types don't undergo any conversion 93 Args(nil).Rets(nil), 94 Args(someType{"foo"}).Rets(someType{"foo"}), 95 }) 96 }