misc: Point to correct simavr include dirs
[simavr] / tests / tests.c
1 #include "tests.h"
2 #include "sim_avr.h"
3 #include "sim_elf.h"
4 #include "sim_core.h"
5 #include "avr_uart.h"
6 #include <stdio.h>
7 #include <setjmp.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdarg.h>
11 #include <unistd.h>
12
13 avr_cycle_count_t tests_cycle_count = 0;
14 int tests_disable_stdout = 1;
15
16 static char *test_name = "(uninitialized test)";
17 static FILE *orig_stderr = NULL;
18 static int finished = 0;
19
20 static void atexit_handler(void) {
21         if (!finished)
22                 _fail(NULL, 0, "Test exit without indicating success.");
23 }
24
25 void tests_success(void) {
26         if (orig_stderr)
27                 stderr = orig_stderr;
28         fprintf(stderr, "OK: %s\n", test_name);
29         finished = 1;
30 }
31
32 void tests_init(int argc, char **argv) {
33         test_name = strdup(argv[0]);
34         atexit(atexit_handler);
35 }
36
37 static avr_cycle_count_t
38 cycle_timer_longjmp_cb(struct avr_t *avr, avr_cycle_count_t when, void *param) {
39         jmp_buf *jmp = param;
40         longjmp(*jmp, LJR_CYCLE_TIMER);
41         return 0;       // clear warning
42 }
43
44 static jmp_buf *special_deinit_jmpbuf = NULL;
45
46 static void special_deinit_longjmp_cb(struct avr_t *avr) {
47         if (special_deinit_jmpbuf)
48                 longjmp(*special_deinit_jmpbuf, LJR_SPECIAL_DEINIT);
49 }
50
51 static int my_avr_run(avr_t * avr)
52 {
53         if (avr->state == cpu_Stopped)
54                 return avr->state;
55
56         uint16_t new_pc = avr->pc;
57
58         if (avr->state == cpu_Running)
59                 new_pc = avr_run_one(avr);
60
61         // if we just re-enabled the interrupts...
62         // double buffer the I flag, to detect that edge
63         if (avr->sreg[S_I] && !avr->i_shadow)
64                 avr->interrupts.pending_wait++;
65         avr->i_shadow = avr->sreg[S_I];
66
67         // run the cycle timers, get the suggested sleep time
68         // until the next timer is due
69         avr_cycle_count_t sleep = avr_cycle_timer_process(avr);
70
71         avr->pc = new_pc;
72
73         if (avr->state == cpu_Sleeping) {
74                 if (!avr->sreg[S_I]) {
75                         printf("simavr: sleeping with interrupts off, quitting gracefully\n");
76                         avr_terminate(avr);
77                         fail("Test case error: special_deinit() returned?");
78                         exit(0);
79                 }
80                 /*
81                  * try to sleep for as long as we can (?)
82                  */
83                 // uint32_t usec = avr_cycles_to_usec(avr, sleep);
84                 // printf("sleep usec %d cycles %d\n", usec, sleep);
85                 // usleep(usec);
86                 avr->cycle += 1 + sleep;
87         }
88         // Interrupt servicing might change the PC too, during 'sleep'
89         if (avr->state == cpu_Running || avr->state == cpu_Sleeping)
90                 avr_service_interrupts(avr);
91         
92         // if we were stepping, use this state to inform remote gdb
93
94         return avr->state;
95 }
96
97 avr_t *tests_init_avr(const char *elfname) {
98         tests_cycle_count = 0;
99         if (tests_disable_stdout) {
100                 orig_stderr = stderr;
101                 fclose(stdout);
102                 stderr = stdout;
103         }
104         elf_firmware_t fw;
105         if (elf_read_firmware(elfname, &fw))
106                 fail("Failed to read ELF firmware \"%s\"", elfname);
107         avr_t *avr = avr_make_mcu_by_name(fw.mmcu);
108         if (!avr)
109                 fail("Creating AVR failed.");
110         avr_init(avr);
111         avr_load_firmware(avr, &fw);
112         return avr;
113 }
114
115 int tests_run_test(avr_t *avr, unsigned long run_usec) {
116         if (!avr)
117                 fail("Internal test error: avr == NULL in run_test()");
118         // register a cycle timer to fire after 100 seconds (simulation time);
119         // assert that the simulation has not finished before that.
120         jmp_buf jmp;
121         special_deinit_jmpbuf = &jmp;
122         avr->special_deinit = special_deinit_longjmp_cb;
123         avr_cycle_timer_register_usec(avr, run_usec,
124                                       cycle_timer_longjmp_cb, &jmp);
125         int reason = setjmp(jmp);
126         tests_cycle_count = avr->cycle;
127         if (reason == 0) {
128                 // setjmp() returned directly, run avr
129                 while (1)
130                         my_avr_run(avr);
131         } else if (reason == 1) {
132                 // returned from longjmp(); cycle timer fired
133                 return reason;
134         } else if (reason == 2) {
135                 // returned from special deinit, avr stopped
136                 return reason;
137         }
138         fail("Error in test case: Should never reach this.");
139         return 0;       
140 }
141
142 int tests_init_and_run_test(const char *elfname, unsigned long run_usec) {
143         avr_t *avr = tests_init_avr(elfname);
144         return tests_run_test(avr, run_usec);
145 }
146
147 struct output_buffer {
148         char *str;
149         int currlen;
150         int alloclen;
151         int maxlen;
152 };
153
154 /* static void buf_output_cb(avr_t *avr, avr_io_addr_t addr, uint8_t v, */
155 /*                        void *param) { */
156 static void buf_output_cb(struct avr_irq_t *irq, uint32_t value, void *param) {
157         struct output_buffer *buf = param;
158         if (!buf)
159                 fail("Internal error: buf == NULL in buf_output_cb()");
160         if (buf->currlen > buf->alloclen-1)
161                 fail("Internal error");
162         if (buf->alloclen == 0)
163                 fail("Internal error");
164         if (buf->currlen == buf->alloclen-1) {
165                 buf->alloclen *= 2;
166                 buf->str = realloc(buf->str, buf->alloclen);
167         }
168         buf->str[buf->currlen++] = value;
169         buf->str[buf->currlen] = 0;
170 }
171
172 static void init_output_buffer(struct output_buffer *buf) {
173         buf->str = malloc(128);
174         buf->str[0] = 0;
175         buf->currlen = 0;
176         buf->alloclen = 128;
177         buf->maxlen = 4096;
178 }
179
180 void tests_assert_uart_receive_avr(avr_t *avr,
181                                unsigned long run_usec,
182                                const char *expected,
183                                char uart) {
184         struct output_buffer buf;
185         init_output_buffer(&buf);
186
187         avr_irq_register_notify(avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUTPUT),
188                                 buf_output_cb, &buf);
189         enum tests_finish_reason reason = tests_run_test(avr, run_usec);
190         if (reason == LJR_CYCLE_TIMER) {
191                 if (strcmp(buf.str, expected) == 0) {
192                         _fail(NULL, 0, "Simulation did not finish within %lu simulated usec. "
193                              "UART output is correct and complete.", run_usec);
194                 }
195                 _fail(NULL, 0, "Simulation did not finish within %lu simulated usec. "
196                      "UART output so far: \"%s\"", run_usec, buf.str);
197         }
198         if (strcmp(buf.str, expected) != 0)
199                 _fail(NULL, 0, "UART outputs differ: expected \"%s\", got \"%s\"", expected, buf.str);
200 }
201
202 void tests_assert_uart_receive(const char *elfname,
203                                unsigned long run_usec,
204                                const char *expected,
205                                char uart) {
206         avr_t *avr = tests_init_avr(elfname);
207
208         tests_assert_uart_receive_avr(avr,
209                                run_usec,
210                                expected,
211                                uart);
212 }
213
214 void tests_assert_cycles_at_least(unsigned long n) {
215         if (tests_cycle_count < n)
216                 _fail(NULL, 0, "Program ran for too few cycles (%"
217                       PRI_avr_cycle_count " < %lu)", tests_cycle_count, n);
218 }
219
220 void tests_assert_cycles_at_most(unsigned long n) {
221         if (tests_cycle_count > n)
222                 _fail(NULL, 0, "Program ran for too many cycles (%"
223                       PRI_avr_cycle_count " > %lu)", tests_cycle_count, n);
224 }
225
226 void tests_assert_cycles_between(unsigned long min, unsigned long max) {
227         tests_assert_cycles_at_least(min);
228         tests_assert_cycles_at_most(max);
229 }
230
231 void _fail(const char *filename, int linenum, const char *fmt, ...) {
232         if (orig_stderr)
233                 stderr = orig_stderr;
234
235         if (filename)
236                 fprintf(stderr, "%s:%d: ", filename, linenum);
237
238         fprintf(stderr, "Test ");
239         if (test_name)
240                 fprintf(stderr, "%s ", test_name);
241         fprintf(stderr, "FAILED.\n");
242
243         if (filename)
244                 fprintf(stderr, "%s:%d: ", filename, linenum);
245
246         va_list va;
247         va_start(va, fmt);
248         vfprintf(stderr, fmt, va);
249         putc('\n', stderr);
250
251         finished = 1;
252         _exit(1);
253 }