github.com/madlambda/nash@v0.2.2-0.20230113003044-f2284521680b/internal/sh/functions_test.go (about) 1 package sh_test 2 3 import "testing" 4 5 func TestFunctionsClosures(t *testing.T) { 6 for _, test := range []execTestCase{ 7 { 8 desc: "simpleClosure", 9 code: ` 10 fn func(a) { 11 fn closure() { 12 print($a) 13 } 14 return $closure 15 } 16 17 var x <= func("1") 18 var y <= func("2") 19 $x() 20 $y() 21 `, 22 expectedStdout: "12", 23 }, 24 { 25 desc: "eachCallCreatesNewVar", 26 code: ` 27 fn func() { 28 var a = () 29 fn add(elem) { 30 a <= append($a, $elem) 31 print("a:%s,",$a) 32 } 33 return $add 34 } 35 36 var add <= func() 37 $add("1") 38 $add("3") 39 $add("5") 40 `, 41 expectedStdout: "a:1,a:1 3,a:1 3 5,", 42 }, 43 { 44 desc: "adder example", 45 code: ` 46 fn makeAdder(x) { 47 fn add(y) { 48 var ret <= expr $x "+" $y 49 return $ret 50 } 51 return $add 52 } 53 54 var add1 <= makeAdder("1") 55 var add5 <= makeAdder("5") 56 var add1000 <= makeAdder("1000") 57 58 print("%s\n", add5("5")) 59 print("%s\n", add5("10")) 60 print("%s\n", add1("10")) 61 print("%s\n", add1("2")) 62 print("%s\n", add1000("50")) 63 print("%s\n", add1000("100")) 64 print("%s\n", add1("10")) 65 `, 66 expectedStdout: `10 67 15 68 11 69 3 70 1050 71 1100 72 11 73 `, 74 }, 75 { 76 desc: "logger", 77 code: `fn getlogger(prefix) { 78 fn log(fmt, args...) { 79 print($prefix+$fmt+"\n", $args...) 80 } 81 82 return $log 83 } 84 85 var info <= getlogger("[info] ") 86 var error <= getlogger("[error] ") 87 var warn <= getlogger("[warn] ") 88 89 $info("nuke initialized successfully") 90 $warn("temperature above anormal circunstances: %s°", "870") 91 $error("about to explode...") 92 `, 93 expectedStdout: `[info] nuke initialized successfully 94 [warn] temperature above anormal circunstances: 870° 95 [error] about to explode... 96 `, 97 }, 98 } { 99 t.Run(test.desc, func(t *testing.T) { 100 testExec(t, test) 101 }) 102 } 103 } 104 105 func TestFunctionsVariables(t *testing.T) { 106 for _, test := range []execTestCase{ 107 { 108 desc: "fn stored only as vars", 109 code: ` 110 fn func(a) { 111 echo -n "hello" 112 } 113 114 func = "teste" 115 echo -n $func 116 func() 117 `, 118 expectedStdout: "teste", 119 expectedErr: "<interactive>:8:4: Identifier 'func' is not a function", 120 }, 121 } { 122 t.Run(test.desc, func(t *testing.T) { 123 testExec(t, test) 124 }) 125 } 126 } 127 128 func TestFunctionsStateless(t *testing.T) { 129 for _, test := range []execTestCase{ 130 { 131 desc: "functions have no shared state", 132 code: `fn iter(first, last, func) { 133 var sequence <= seq $first $last 134 var range <= split($sequence, "\n") 135 for i in $range { 136 $func($i) 137 } 138 } 139 140 fn create_vm(index) { 141 echo "create_vm: "+$index 142 iter("1", "3", $create_disk) 143 } 144 145 fn create_disk(index) { 146 echo "create_disk: " + $index 147 } 148 149 iter("1", "2", $create_vm) 150 `, 151 expectedStdout: `create_vm: 1 152 create_disk: 1 153 create_disk: 2 154 create_disk: 3 155 create_vm: 2 156 create_disk: 1 157 create_disk: 2 158 create_disk: 3 159 `, 160 }, 161 } { 162 t.Run(test.desc, func(t *testing.T) { 163 testExec(t, test) 164 }) 165 } 166 }