blob: e9183290c6a54332fd253ae4b04869630579656b [file] [log] [blame]
reed@android.come50025a2009-09-01 21:00:44 +00001#include "Forth.h"
2#include "SkString.h"
3
4class Reporter {
5public:
6 int fFailureCount;
7
8 Reporter() : fFailureCount(0) {}
9 void reportFailure(const char expression[], const char file[], int line);
10 void reportFailure(const char msg[]);
11};
12
13typedef void (*ForthWordTestProc)(ForthWord*, ForthEngine*, Reporter*);
14
15#define FORTH_ASSERT(reporter, expression) \
16 do { \
17 if (!(expression)) { \
18 reporter->reportFailure(#expression, __FILE__, __LINE__); \
19 } \
20 } while (0)
21
22static void drop_test0(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
23 fe->push(-17);
24 word->exec(fe);
25 FORTH_ASSERT(reporter, 0 == fe->depth());
26}
27
28static void drop_test1(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
29 fe->push(-17);
30 fe->push(93);
31 word->exec(fe);
32 FORTH_ASSERT(reporter, 1 == fe->depth());
33 FORTH_ASSERT(reporter, -17 == fe->peek(0));
34}
35
36static void dup_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
37 fe->push(-17);
38 word->exec(fe);
39 FORTH_ASSERT(reporter, 2 == fe->depth());
40 FORTH_ASSERT(reporter, -17 == fe->peek(0));
41 FORTH_ASSERT(reporter, -17 == fe->peek(1));
42}
43
44static void swap_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
45 fe->push(-17);
46 fe->push(42);
47 word->exec(fe);
48 FORTH_ASSERT(reporter, 2 == fe->depth());
49 FORTH_ASSERT(reporter, -17 == fe->peek(0));
50 FORTH_ASSERT(reporter, 42 == fe->peek(1));
51}
52
53static void over_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
54 fe->push(1);
55 fe->push(2);
56 word->exec(fe);
57 FORTH_ASSERT(reporter, 3 == fe->depth());
58 FORTH_ASSERT(reporter, 1 == fe->peek(0));
59 FORTH_ASSERT(reporter, 2 == fe->peek(1));
60 FORTH_ASSERT(reporter, 1 == fe->peek(2));
61}
62
63static void rot_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
64 fe->push(1);
65 fe->push(2);
66 fe->push(3);
67 word->exec(fe);
68 FORTH_ASSERT(reporter, 3 == fe->depth());
69 FORTH_ASSERT(reporter, 2 == fe->peek(2));
70 FORTH_ASSERT(reporter, 3 == fe->peek(1));
71 FORTH_ASSERT(reporter, 1 == fe->peek(0));
72}
73
74static void rrot_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
75 fe->push(1);
76 fe->push(2);
77 fe->push(3);
78 word->exec(fe);
79 FORTH_ASSERT(reporter, 3 == fe->depth());
80 FORTH_ASSERT(reporter, 2 == fe->peek(0));
81 FORTH_ASSERT(reporter, 1 == fe->peek(1));
82 FORTH_ASSERT(reporter, 3 == fe->peek(2));
83}
84
85static void swap2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
86 fe->push(1);
87 fe->push(2);
88 fe->push(3);
89 fe->push(4);
90 word->exec(fe);
91 FORTH_ASSERT(reporter, 4 == fe->depth());
92 FORTH_ASSERT(reporter, 2 == fe->peek(0));
93 FORTH_ASSERT(reporter, 1 == fe->peek(1));
94 FORTH_ASSERT(reporter, 4 == fe->peek(2));
95 FORTH_ASSERT(reporter, 3 == fe->peek(3));
96}
97
98static void dup2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
99 fe->push(1);
100 fe->push(2);
101 word->exec(fe);
102 FORTH_ASSERT(reporter, 4 == fe->depth());
103 FORTH_ASSERT(reporter, 1 == fe->peek(3));
104 FORTH_ASSERT(reporter, 2 == fe->peek(2));
105 FORTH_ASSERT(reporter, 1 == fe->peek(1));
106 FORTH_ASSERT(reporter, 2 == fe->peek(0));
107}
108
109static void over2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
110 fe->push(1);
111 fe->push(2);
112 fe->push(3);
113 fe->push(4);
114 word->exec(fe);
115 FORTH_ASSERT(reporter, 6 == fe->depth());
116 FORTH_ASSERT(reporter, 1 == fe->peek(5));
117 FORTH_ASSERT(reporter, 2 == fe->peek(4));
118 FORTH_ASSERT(reporter, 3 == fe->peek(3));
119 FORTH_ASSERT(reporter, 4 == fe->peek(2));
120 FORTH_ASSERT(reporter, 1 == fe->peek(1));
121 FORTH_ASSERT(reporter, 2 == fe->peek(0));
122}
123
124static void drop2_test(ForthWord* word, ForthEngine* fe, Reporter* reporter) {
125 fe->push(1);
126 fe->push(2);
127 fe->push(3);
128 fe->push(4);
129 word->exec(fe);
130 FORTH_ASSERT(reporter, 2 == fe->depth());
131 FORTH_ASSERT(reporter, 1 == fe->peek(1));
132 FORTH_ASSERT(reporter, 2 == fe->peek(0));
133}
134
135static const struct {
136 const char* fName;
137 ForthWordTestProc fProc;
138} gRecs[] = {
139 { "DROP", drop_test0 }, { "DROP", drop_test1 },
140 { "DUP", dup_test },
141 { "SWAP", swap_test },
142 { "OVER", over_test },
143 { "ROT", rot_test },
144 { "-ROT", rrot_test },
145 { "2SWAP", swap2_test },
146 { "2DUP", dup2_test },
147 { "2OVER", over2_test },
148 { "2DROP", drop2_test },
149};
150
151///////////////////////////////////////////////////////////////////////////////
152
153void Reporter::reportFailure(const char expression[], const char file[],
154 int line) {
155 SkDebugf("failed %s:%d: %s\n", file, line, expression);
156 fFailureCount += 1;
157}
158
159void Reporter::reportFailure(const char msg[]) {
160 SkDebugf("%s\n");
161 fFailureCount += 1;
162}
163
164void Forth_test_stdwords();
165void Forth_test_stdwords() {
166 ForthEnv env;
167 Reporter reporter;
168
169 for (size_t i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
170 ForthEngine engine(NULL);
171
172 ForthWord* word = env.findWord(gRecs[i].fName);
173 if (NULL == word) {
174 SkString str;
175 str.printf("--- can't find stdword %d", gRecs[i].fName);
176 reporter.reportFailure(str.c_str());
177 } else {
178 gRecs[i].fProc(word, &engine, &reporter);
179 }
180 }
181
182 if (0 == reporter.fFailureCount) {
183 SkDebugf("--- success!\n");
184 } else {
185 SkDebugf("--- %d failures\n", reporter.fFailureCount);
186 }
187}
188