cuelang.org/go@v0.10.1/pkg/tool/os/env_test.go (about)

     1  // Copyright 2019 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 os
    16  
    17  import (
    18  	"os"
    19  	"testing"
    20  
    21  	"github.com/google/go-cmp/cmp"
    22  	"github.com/google/go-cmp/cmp/cmpopts"
    23  
    24  	"cuelang.org/go/cue"
    25  	"cuelang.org/go/cue/ast"
    26  	"cuelang.org/go/cue/errors"
    27  	"cuelang.org/go/cue/parser"
    28  	"cuelang.org/go/cue/token"
    29  	"cuelang.org/go/internal/task"
    30  	"cuelang.org/go/internal/value"
    31  	"cuelang.org/go/pkg/internal"
    32  )
    33  
    34  func TestGetenv(t *testing.T) {
    35  
    36  	for _, p := range [][2]string{
    37  		{"CUEOSTESTMOOD", "yippie"},
    38  		{"CUEOSTESTTRUE", "True"},
    39  		{"CUEOSTESTFALSE", "0"},
    40  		{"CUEOSTESTBI", "1"},
    41  		{"CUEOSTESTNUM", "34K"},
    42  		{"CUEOSTESTNUMD", "not a num"},
    43  		{"CUEOSTESTMULTI", "10"},
    44  	} {
    45  		t.Setenv(p[0], p[1])
    46  	}
    47  
    48  	config := `{
    49  		CUEOSTESTMOOD:  string
    50  		CUEOSTESTTRUE:  bool
    51  		CUEOSTESTFALSE: bool | string
    52  		CUEOSTESTBI: 	*bool | int,
    53  		CUEOSTESTNUM:   int
    54  		CUEOSTESTNUMD:  *int | *bool | string
    55  		CUEOSTESTMULTI: *<10 | string
    56  		CUEOSTESTNULL:  int | null
    57  	}`
    58  
    59  	want := map[string]interface{}{
    60  		"CUEOSTESTMOOD": ast.NewString("yippie"),
    61  		"CUEOSTESTTRUE": ast.NewBool(true),
    62  		"CUEOSTESTFALSE": &ast.BinaryExpr{
    63  			Op: token.OR,
    64  			X:  ast.NewBool(false),
    65  			Y:  ast.NewString("0"),
    66  		},
    67  		"CUEOSTESTBI": &ast.BinaryExpr{
    68  			Op: token.OR,
    69  			X:  ast.NewLit(token.INT, "1"),
    70  			Y:  ast.NewBool(true),
    71  		},
    72  		"CUEOSTESTNUM":  &ast.BasicLit{Kind: token.INT, Value: "34K"},
    73  		"CUEOSTESTNUMD": ast.NewString("not a num"),
    74  		"CUEOSTESTMULTI": &ast.BinaryExpr{
    75  			Op: token.OR,
    76  			X:  ast.NewLit(token.INT, "10"),
    77  			Y:  ast.NewString("10"),
    78  		},
    79  		"CUEOSTESTNULL": nil,
    80  	}
    81  
    82  	for _, tc := range []struct {
    83  		pkg    string
    84  		runner task.Runner
    85  	}{
    86  		{"tool/os.Getenv", &getenvCmd{}},
    87  		{"tool/os.Environ", &environCmd{}},
    88  	} {
    89  		v := parse(t, tc.pkg, config)
    90  		got, err := tc.runner.Run(&task.Context{Obj: v})
    91  		if err != nil {
    92  			t.Fatal(err)
    93  		}
    94  
    95  		var opts = []cmp.Option{
    96  			cmpopts.IgnoreFields(ast.BinaryExpr{}, "OpPos"),
    97  			cmpopts.IgnoreFields(ast.BasicLit{}, "ValuePos"),
    98  			cmpopts.IgnoreUnexported(ast.BasicLit{}, ast.BinaryExpr{}),
    99  			// For ignoring addinonal entries from os.Environ:
   100  			cmpopts.IgnoreMapEntries(func(s string, x interface{}) bool {
   101  				_, ok := want[s]
   102  				return !ok
   103  			}),
   104  		}
   105  
   106  		if diff := cmp.Diff(got, want, opts...); diff != "" {
   107  			t.Error(diff)
   108  		}
   109  
   110  		// Errors:
   111  		for _, etc := range []struct{ config, err string }{{
   112  			config: `{ CUEOSTESTNULL:  [...string] }`,
   113  			err:    "expected unsupported type error",
   114  		}, {
   115  			config: `{ CUEOSTESTNUMD: int }`,
   116  			err:    "expected invalid number error",
   117  		}, {
   118  			config: `{ CUEOSTESTNUMD: null }`,
   119  			err:    "expected invalid type",
   120  		}} {
   121  			t.Run(etc.err, func(t *testing.T) {
   122  				v = parse(t, tc.pkg, etc.config)
   123  				if _, err = tc.runner.Run(&task.Context{Obj: v}); err == nil {
   124  					t.Error(etc.err)
   125  				}
   126  			})
   127  		}
   128  	}
   129  }
   130  
   131  func parse(t *testing.T, kind, expr string) cue.Value {
   132  	t.Helper()
   133  
   134  	x, err := parser.ParseExpr("test", expr)
   135  	if err != nil {
   136  		errors.Print(os.Stderr, err, nil)
   137  		t.Fatal(err)
   138  	}
   139  	ctx := internal.NewContext()
   140  	v := ctx.BuildExpr(x)
   141  	if err := v.Err(); err != nil {
   142  		t.Fatal(err)
   143  	}
   144  	return value.UnifyBuiltin(v, kind)
   145  }