github.com/mattn/anko@v0.1.10/vm/packages_test.go (about)

     1  package vm
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/mattn/anko/env"
     9  	_ "github.com/mattn/anko/packages"
    10  )
    11  
    12  func TestImport(t *testing.T) {
    13  	tests := []Test{
    14  		{Script: `a = import(1++)`, RunError: fmt.Errorf("invalid operation")},
    15  		{Script: `a = import(true)`, RunError: fmt.Errorf("invalid type conversion")},
    16  		{Script: `a = import("foo")`, RunError: fmt.Errorf("package not found: foo")},
    17  	}
    18  	runTests(t, tests, nil, &Options{Debug: true})
    19  
    20  	envPackages := env.Packages
    21  	envPackageTypes := env.PackageTypes
    22  
    23  	env.Packages = map[string]map[string]reflect.Value{"testPackage": {"a.b": reflect.ValueOf(1)}}
    24  	tests = []Test{
    25  		{Script: `a = import("testPackage")`, RunError: fmt.Errorf("import DefineValue error: symbol contains '.'")},
    26  	}
    27  	runTests(t, tests, nil, &Options{Debug: true})
    28  
    29  	env.Packages = map[string]map[string]reflect.Value{"testPackage": {"a": reflect.ValueOf(1)}}
    30  	env.PackageTypes = map[string]map[string]reflect.Type{"testPackage": {"a.b": reflect.TypeOf(1)}}
    31  	tests = []Test{
    32  		{Script: `a = import("testPackage")`, RunError: fmt.Errorf("import DefineReflectType error: symbol contains '.'")},
    33  	}
    34  	runTests(t, tests, nil, &Options{Debug: true})
    35  
    36  	env.PackageTypes = envPackageTypes
    37  	env.Packages = envPackages
    38  }
    39  
    40  func TestPackagesBytes(t *testing.T) {
    41  	t.Parallel()
    42  
    43  	tests := []Test{
    44  		{Script: `bytes = import("bytes"); a = make(bytes.Buffer); n, err = a.WriteString("a"); if err != nil { return err }; n`, RunOutput: 1},
    45  		{Script: `bytes = import("bytes"); a = make(bytes.Buffer); n, err = a.WriteString("a"); if err != nil { return err }; a.String()`, RunOutput: "a"},
    46  	}
    47  	runTests(t, tests, nil, &Options{Debug: true})
    48  }
    49  
    50  func TestPackagesJson(t *testing.T) {
    51  	t.Parallel()
    52  
    53  	tests := []Test{
    54  		{Script: `json = import("encoding/json"); a = make(map[string]interface); a["b"] = "b"; c, err = json.Marshal(a); err`, Output: map[string]interface{}{"a": map[string]interface{}{"b": "b"}, "c": []byte(`{"b":"b"}`)}},
    55  		{Script: `json = import("encoding/json"); b = 1; err = json.Unmarshal(a, &b); err`, Input: map[string]interface{}{"a": []byte(`{"b": "b"}`)}, Output: map[string]interface{}{"a": []byte(`{"b": "b"}`), "b": map[string]interface{}{"b": "b"}}},
    56  		{Script: `json = import("encoding/json"); b = 1; err = json.Unmarshal(a, &b); err`, Input: map[string]interface{}{"a": `{"b": "b"}`}, Output: map[string]interface{}{"a": `{"b": "b"}`, "b": map[string]interface{}{"b": "b"}}},
    57  		{Script: `json = import("encoding/json"); b = 1; err = json.Unmarshal(a, &b); err`, Input: map[string]interface{}{"a": `[["1", "2"],["3", "4"]]`}, Output: map[string]interface{}{"a": `[["1", "2"],["3", "4"]]`, "b": []interface{}{[]interface{}{"1", "2"}, []interface{}{"3", "4"}}}},
    58  	}
    59  	runTests(t, tests, nil, &Options{Debug: true})
    60  }
    61  
    62  func TestPackagesRegexp(t *testing.T) {
    63  	t.Parallel()
    64  
    65  	tests := []Test{
    66  		{Script: `regexp = import("regexp"); re = regexp.MustCompile("^simple$"); re.MatchString("simple")`, RunOutput: true},
    67  		{Script: `regexp = import("regexp"); re = regexp.MustCompile("^simple$"); re.MatchString("no match")`, RunOutput: false},
    68  
    69  		{Script: `regexp = import("regexp"); re = regexp.MustCompile(a); re.MatchString(b)`, Input: map[string]interface{}{"a": "^simple$", "b": "simple"}, RunOutput: true, Output: map[string]interface{}{"a": "^simple$", "b": "simple"}},
    70  		{Script: `regexp = import("regexp"); re = regexp.MustCompile(a); re.MatchString(b)`, Input: map[string]interface{}{"a": "^simple$", "b": "no match"}, RunOutput: false, Output: map[string]interface{}{"a": "^simple$", "b": "no match"}},
    71  
    72  		{Script: `regexp = import("regexp"); re = regexp.MustCompile("^a\\.\\d+\\.b$"); re.String()`, RunOutput: "^a\\.\\d+\\.b$"},
    73  		{Script: `regexp = import("regexp"); re = regexp.MustCompile("^a\\.\\d+\\.b$"); re.MatchString("a.1.b")`, RunOutput: true},
    74  		{Script: `regexp = import("regexp"); re = regexp.MustCompile("^a\\.\\d+\\.b$"); re.MatchString("a.22.b")`, RunOutput: true},
    75  		{Script: `regexp = import("regexp"); re = regexp.MustCompile("^a\\.\\d+\\.b$"); re.MatchString("a.333.b")`, RunOutput: true},
    76  		{Script: `regexp = import("regexp"); re = regexp.MustCompile("^a\\.\\d+\\.b$"); re.MatchString("no match")`, RunOutput: false},
    77  		{Script: `regexp = import("regexp"); re = regexp.MustCompile("^a\\.\\d+\\.b$"); re.MatchString("a+1+b")`, RunOutput: false},
    78  
    79  		{Script: `regexp = import("regexp"); re = regexp.MustCompile(a); re.String()`, Input: map[string]interface{}{"a": "^a\\.\\d+\\.b$"}, RunOutput: "^a\\.\\d+\\.b$", Output: map[string]interface{}{"a": "^a\\.\\d+\\.b$"}},
    80  		{Script: `regexp = import("regexp"); re = regexp.MustCompile(a); re.MatchString(b)`, Input: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "a.1.b"}, RunOutput: true, Output: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "a.1.b"}},
    81  		{Script: `regexp = import("regexp"); re = regexp.MustCompile(a); re.MatchString(b)`, Input: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "a.22.b"}, RunOutput: true, Output: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "a.22.b"}},
    82  		{Script: `regexp = import("regexp"); re = regexp.MustCompile(a); re.MatchString(b)`, Input: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "a.333.b"}, RunOutput: true, Output: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "a.333.b"}},
    83  		{Script: `regexp = import("regexp"); re = regexp.MustCompile(a); re.MatchString(b)`, Input: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "no match"}, RunOutput: false, Output: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "no match"}},
    84  		{Script: `regexp = import("regexp"); re = regexp.MustCompile(a); re.MatchString(b)`, Input: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "a+1+b"}, RunOutput: false, Output: map[string]interface{}{"a": "^a\\.\\d+\\.b$", "b": "a+1+b"}},
    85  	}
    86  	runTests(t, tests, nil, &Options{Debug: true})
    87  }
    88  
    89  func TestPackagesSort(t *testing.T) {
    90  	t.Parallel()
    91  
    92  	tests := []Test{
    93  		{Script: `sort = import("sort"); a = make([]int); a += [5, 3, 1, 4, 2]; sort.Ints(a); a`, RunOutput: []int{1, 2, 3, 4, 5}, Output: map[string]interface{}{"a": []int{1, 2, 3, 4, 5}}},
    94  		{Script: `sort = import("sort"); a = make([]float64); a += [5.5, 3.3, 1.1, 4.4, 2.2]; sort.Float64s(a); a`, RunOutput: []float64{1.1, 2.2, 3.3, 4.4, 5.5}, Output: map[string]interface{}{"a": []float64{1.1, 2.2, 3.3, 4.4, 5.5}}},
    95  		{Script: `sort = import("sort"); a = make([]string); a += ["e", "c", "a", "d", "b"]; sort.Strings(a); a`, RunOutput: []string{"a", "b", "c", "d", "e"}, Output: map[string]interface{}{"a": []string{"a", "b", "c", "d", "e"}}},
    96  		{Script: `
    97  sort = import("sort")
    98  a = [5, 1.1, 3, "f", "2", "4.4"]
    99  sortFuncs = make(sort.SortFuncsStruct)
   100  sortFuncs.LenFunc = func() { return len(a) }
   101  sortFuncs.LessFunc = func(i, j) { return a[i] < a[j] }
   102  sortFuncs.SwapFunc = func(i, j) { temp = a[i]; a[i] = a[j]; a[j] = temp }
   103  sort.Sort(sortFuncs)
   104  a
   105  `,
   106  			RunOutput: []interface{}{"f", float64(1.1), "2", int64(3), "4.4", int64(5)}, Output: map[string]interface{}{"a": []interface{}{"f", float64(1.1), "2", int64(3), "4.4", int64(5)}}},
   107  	}
   108  	runTests(t, tests, nil, &Options{Debug: true})
   109  }
   110  
   111  func TestPackagesStrconv(t *testing.T) {
   112  	t.Parallel()
   113  
   114  	var toRune = func(s string) rune {
   115  		if len(s) == 0 {
   116  			return 0
   117  		}
   118  		return []rune(s)[0]
   119  	}
   120  	var toString = func(v interface{}) string {
   121  		if b, ok := v.([]byte); ok {
   122  			return string(b)
   123  		}
   124  		return fmt.Sprint(v)
   125  	}
   126  	tests := []Test{
   127  		{Script: `strconv = import("strconv"); a = true; b = strconv.FormatBool(a)`, RunOutput: "true", Output: map[string]interface{}{"a": true, "b": "true"}},
   128  		{Script: `strconv = import("strconv"); a = 1.1; b = strconv.FormatFloat(a, toRune("f"), -1, 64)`, Input: map[string]interface{}{"toRune": toRune}, RunOutput: "1.1", Output: map[string]interface{}{"a": float64(1.1), "b": "1.1"}},
   129  		{Script: `strconv = import("strconv"); a = 1; b = strconv.FormatInt(a, 10)`, RunOutput: "1", Output: map[string]interface{}{"a": int64(1), "b": "1"}},
   130  		{Script: `strconv = import("strconv"); b = strconv.FormatInt(a, 10)`, Input: map[string]interface{}{"a": uint64(1)}, RunOutput: "1", Output: map[string]interface{}{"a": uint64(1), "b": "1"}},
   131  
   132  		{Script: `strconv = import("strconv"); a = "true"; b, err = strconv.ParseBool(a); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: "<nil>", Output: map[string]interface{}{"a": "true", "b": true, "err": "<nil>"}},
   133  		{Script: `strconv = import("strconv"); a = "2"; b, err = strconv.ParseBool(a); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseBool: parsing "2": invalid syntax`, Output: map[string]interface{}{"a": "2", "b": false, "err": `strconv.ParseBool: parsing "2": invalid syntax`}},
   134  		{Script: `strconv = import("strconv"); a = "1.1"; b, err = strconv.ParseFloat(a, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: "<nil>", Output: map[string]interface{}{"a": "1.1", "b": float64(1.1), "err": "<nil>"}},
   135  		{Script: `strconv = import("strconv"); a = "a"; b, err = strconv.ParseFloat(a, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseFloat: parsing "a": invalid syntax`, Output: map[string]interface{}{"a": "a", "b": float64(0), "err": `strconv.ParseFloat: parsing "a": invalid syntax`}},
   136  		{Script: `strconv = import("strconv"); a = "1"; b, err = strconv.ParseInt(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: "<nil>", Output: map[string]interface{}{"a": "1", "b": int64(1), "err": "<nil>"}},
   137  		{Script: `strconv = import("strconv"); a = "1.1"; b, err = strconv.ParseInt(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseInt: parsing "1.1": invalid syntax`, Output: map[string]interface{}{"a": "1.1", "b": int64(0), "err": `strconv.ParseInt: parsing "1.1": invalid syntax`}},
   138  		{Script: `strconv = import("strconv"); a = "a"; b, err = strconv.ParseInt(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseInt: parsing "a": invalid syntax`, Output: map[string]interface{}{"a": "a", "b": int64(0), "err": `strconv.ParseInt: parsing "a": invalid syntax`}},
   139  		{Script: `strconv = import("strconv"); a = "1"; b, err = strconv.ParseUint(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: "<nil>", Output: map[string]interface{}{"a": "1", "b": uint64(1), "err": "<nil>"}},
   140  		{Script: `strconv = import("strconv"); a = "a"; b, err = strconv.ParseUint(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseUint: parsing "a": invalid syntax`, Output: map[string]interface{}{"a": "a", "b": uint64(0), "err": `strconv.ParseUint: parsing "a": invalid syntax`}},
   141  
   142  		{Script: `strconv = import("strconv"); a = "true"; var b, err = strconv.ParseBool(a); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: "<nil>", Output: map[string]interface{}{"a": "true", "b": true, "err": "<nil>"}},
   143  		{Script: `strconv = import("strconv"); a = "2"; var b, err = strconv.ParseBool(a); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseBool: parsing "2": invalid syntax`, Output: map[string]interface{}{"a": "2", "b": false, "err": `strconv.ParseBool: parsing "2": invalid syntax`}},
   144  		{Script: `strconv = import("strconv"); a = "1.1"; var b, err = strconv.ParseFloat(a, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: "<nil>", Output: map[string]interface{}{"a": "1.1", "b": float64(1.1), "err": "<nil>"}},
   145  		{Script: `strconv = import("strconv"); a = "a"; var b, err = strconv.ParseFloat(a, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseFloat: parsing "a": invalid syntax`, Output: map[string]interface{}{"a": "a", "b": float64(0), "err": `strconv.ParseFloat: parsing "a": invalid syntax`}},
   146  		{Script: `strconv = import("strconv"); a = "1"; var b, err = strconv.ParseInt(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: "<nil>", Output: map[string]interface{}{"a": "1", "b": int64(1), "err": "<nil>"}},
   147  		{Script: `strconv = import("strconv"); a = "1.1"; var b, err = strconv.ParseInt(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseInt: parsing "1.1": invalid syntax`, Output: map[string]interface{}{"a": "1.1", "b": int64(0), "err": `strconv.ParseInt: parsing "1.1": invalid syntax`}},
   148  		{Script: `strconv = import("strconv"); a = "a"; var b, err = strconv.ParseInt(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseInt: parsing "a": invalid syntax`, Output: map[string]interface{}{"a": "a", "b": int64(0), "err": `strconv.ParseInt: parsing "a": invalid syntax`}},
   149  		{Script: `strconv = import("strconv"); a = "1"; var b, err = strconv.ParseUint(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: "<nil>", Output: map[string]interface{}{"a": "1", "b": uint64(1), "err": "<nil>"}},
   150  		{Script: `strconv = import("strconv"); a = "a"; var b, err = strconv.ParseUint(a, 10, 64); err = toString(err)`, Input: map[string]interface{}{"toString": toString}, RunOutput: `strconv.ParseUint: parsing "a": invalid syntax`, Output: map[string]interface{}{"a": "a", "b": uint64(0), "err": `strconv.ParseUint: parsing "a": invalid syntax`}},
   151  	}
   152  	runTests(t, tests, nil, &Options{Debug: true})
   153  }
   154  
   155  func TestPackagesStrings(t *testing.T) {
   156  	t.Parallel()
   157  
   158  	tests := []Test{
   159  		{Script: `strings = import("strings"); a = " one two "; b = strings.TrimSpace(a)`, RunOutput: "one two", Output: map[string]interface{}{"a": " one two ", "b": "one two"}},
   160  		{Script: `strings = import("strings"); a = "a b c d"; b = strings.Split(a, " ")`, RunOutput: []string{"a", "b", "c", "d"}, Output: map[string]interface{}{"a": "a b c d", "b": []string{"a", "b", "c", "d"}}},
   161  		{Script: `strings = import("strings"); a = "a b c d"; b = strings.SplitN(a, " ", 3)`, RunOutput: []string{"a", "b", "c d"}, Output: map[string]interface{}{"a": "a b c d", "b": []string{"a", "b", "c d"}}},
   162  	}
   163  	runTests(t, tests, nil, &Options{Debug: true})
   164  }
   165  
   166  func TestPackagesSync(t *testing.T) {
   167  	t.Parallel()
   168  
   169  	tests := []Test{
   170  		{Script: `sync = import("sync"); once = make(sync.Once); a = []; func add() { a += "a" }; once.Do(add); once.Do(add); a`, RunOutput: []interface{}{"a"}, Output: map[string]interface{}{"a": []interface{}{"a"}}},
   171  		{Script: `sync = import("sync"); waitGroup = make(sync.WaitGroup); waitGroup.Add(2);  func done() { waitGroup.Done() }; go done(); go done(); waitGroup.Wait(); "a"`, RunOutput: "a"},
   172  	}
   173  	runTests(t, tests, nil, &Options{Debug: true})
   174  }
   175  
   176  func TestPackagesTime(t *testing.T) {
   177  	t.Parallel()
   178  
   179  	tests := []Test{
   180  		{Script: `time = import("time"); a = make(time.Time); a.IsZero()`, RunOutput: true},
   181  	}
   182  	runTests(t, tests, nil, &Options{Debug: true})
   183  }
   184  
   185  func TestPackagesURL(t *testing.T) {
   186  	t.Parallel()
   187  
   188  	e := env.NewEnv()
   189  	value, err := Execute(e, nil, `
   190  url = import("net/url")
   191  v1 = make(url.Values)
   192  v1.Set("a", "a")
   193  if v1.Get("a") != "a" {
   194  	return "value a not set"
   195  } 
   196  v2 = make(url.Values) 
   197  v2.Set("b", "b")
   198  if v2.Get("b") != "b" {
   199  	return "value b not set"
   200  } 
   201  v2.Get("a")
   202  `)
   203  	if err != nil {
   204  		t.Errorf("execute error - received: %v expected: %v", err, nil)
   205  	}
   206  	if value != "" {
   207  		t.Errorf("execute value - received: %#v expected: %#v", value, "")
   208  	}
   209  }