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  }