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  }