github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/forth/forth_test.go (about) 1 // Copyright 2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package forth 6 7 import ( 8 "fmt" 9 "os" 10 "reflect" 11 "testing" 12 ) 13 14 type forthTest struct { 15 val string 16 res Cell 17 err string 18 } 19 20 var forthTests = []forthTest{ 21 {"hostname", "", ""}, 22 {"2", "2", ""}, 23 {"", "", "[]: length is not 1"}, 24 {"2 2 +", "4", ""}, 25 {"4 2 -", "2", ""}, 26 {"4 2 *", "8", ""}, 27 {"4 2 /", "2", ""}, 28 {"5 2 %", "1", ""}, 29 {"sb43 hostbase", "43", ""}, 30 {"sb43 hostbase dup 20 / swap 20 % dup ifelse", "3", ""}, 31 {"sb40 hostbase dup 20 / swap 20 % dup ifelse", "2", ""}, 32 {"2 4 swap /", "2", ""}, 33 {"0 1 1 ifelse", "1", ""}, 34 {"0 1 0 ifelse", "0", ""}, 35 {"str cat strcat", "strcat", ""}, 36 {"1 dup +", "2", ""}, 37 {"4095 4096 roundup", "4096", ""}, 38 {"4097 8192 roundup", "8192", ""}, 39 {"2 x +", nil, "parsing \"x\": invalid syntax"}, 40 {"1 dd +", "2", ""}, 41 {"1 d3d", "3", ""}, 42 } 43 44 func TestForth(t *testing.T) { 45 46 forthTests[0].res, _ = os.Hostname() 47 f := New() 48 if f.Length() != 0 { 49 t.Errorf("Test: stack is %d and should be 0", f.Length()) 50 } 51 if f.Empty() != true { 52 t.Errorf("Test: stack is %v and should be false", f.Empty()) 53 } 54 f.Push("test") 55 if f.Length() != 1 { 56 t.Errorf("Test: stack is %d and should be 1", f.Length()) 57 } 58 if f.Empty() == true { 59 t.Errorf("Test: stack is %v and should be false", f.Empty()) 60 } 61 f.Reset() 62 if f.Length() != 0 { 63 t.Errorf("Test: After Reset(): stack is %d and should be 0", f.Length()) 64 } 65 if f.Empty() != true { 66 t.Errorf("Test: After Reset(): stack is %v and should be true", f.Empty()) 67 } 68 NewWord(f, "dd", "dup") 69 NewWord(f, "d3d", "dup", "dup", "+", "+") 70 for _, tt := range forthTests { 71 var err error 72 res, err := EvalPop(f, tt.val) 73 t.Logf("tt %v res %v err %v", tt, res, err) 74 if res == tt.res || (err != nil && err.Error() == tt.err) { 75 if err != nil { 76 /* stack is not going to be right; reset it. */ 77 f.Reset() 78 } 79 t.Logf("Test: '%v' '%v' '%v': Pass\n", tt.val, res, err) 80 } else { 81 t.Errorf("Test: '%v' got (%v, %v): want (%v, %v): Fail\n", tt.val, res, err, tt.res, tt.err) 82 t.Logf("ops %v\n", Ops()) 83 continue 84 } 85 if f.Length() != 0 { 86 t.Errorf("Test: %v: stack is %d and should be empty", tt, f.Length()) 87 } 88 if f.Empty() != true { 89 t.Errorf("Test: %v: stack is %v and should be empty", tt, f.Empty()) 90 } 91 } 92 93 } 94 95 func TestBadPop(t *testing.T) { 96 var b [3]byte 97 f := New() 98 f.Push(b) 99 res, err := EvalPop(f, "2 +") 100 t.Logf("%v, %v", res, err) 101 nan := fmt.Errorf("NaN: %T", b) 102 if !reflect.DeepEqual(err, nan) { 103 t.Errorf("got %v, want %v", err, nan) 104 } 105 if res != nil { 106 t.Errorf("got %v, want nil", res) 107 } 108 } 109 110 func TestOpmap(t *testing.T) { 111 f := New() 112 err := Eval(f, "words") 113 if err != nil { 114 t.Fatalf("words: got %v, nil", err) 115 } 116 if f.Length() != 1 { 117 t.Fatalf("words: got length %d, want 1", f.Length()) 118 } 119 w := f.Pop() 120 switch w.(type) { 121 case []string: 122 default: 123 t.Fatalf("words: got %T, want []string", w) 124 } 125 t.Logf("words are %v", w) 126 } 127 128 func TestNewWord(t *testing.T) { 129 Debug = t.Logf 130 f := New() 131 // This test creates a word, tp, with 3 args, which simply 132 // pushes 1 and 3 on the stack and applies +. 133 // Note the use of ' so we can evaluate + as a string, 134 // not an operator. 135 err := Eval(f, "1", "3", "'+", "3", "tp", "newword") 136 if err != nil { 137 t.Fatalf("newword: got %v, nil", err) 138 } 139 err = Eval(f, "tp") 140 if err != nil { 141 t.Fatalf("newword: got %v, want nil", err) 142 } 143 t.Logf("stack %v", f.Stack()) 144 } 145 146 // make sure that if we die in an Eval nested in an Eval, we fall all the way 147 // back out. 148 func TestEvalPanic(t *testing.T) { 149 f := New() 150 Debug = t.Logf 151 err := Eval(f, "0", "'+", "2", "p", "newword") 152 if err != nil { 153 t.Fatalf("newword: got %v, nil", err) 154 } 155 t.Logf("p created, now try problems") 156 err = Eval(f, "0", uint8(0), "+") 157 if err == nil { 158 t.Fatal("Got nil, want error") 159 } 160 t.Logf("Test plus with wrong types: %v", err) 161 f.Reset() 162 err = Eval(f, "p") 163 if err == nil { 164 t.Fatal("P with too few args: Got nil, want error") 165 } 166 t.Logf("p with too few args: %v", err) 167 err2 := Eval(f, "p", "0", uint8(0), "+") 168 if err2.Error() != err.Error() { 169 t.Fatalf("Got %v, want %v", err2, err) 170 } 171 }