Refresh and improve test runner
e5efba42239c6f64b6709165e003cb7b915495d19addc4221dae20a0f872197c
1 parent
461ef29e
test/runner.rad
+37 -14
| 25 | 25 | constant OUTPUT_BUF_SIZE: u32 = 32768; |
|
| 26 | 26 | /// Arena size for AST/IL allocations (512 KB). |
|
| 27 | 27 | constant ARENA_SIZE: u32 = 524288; |
|
| 28 | 28 | /// Maximum path length for expected IL file path. |
|
| 29 | 29 | constant MAX_PATH_LEN: u32 = 256; |
|
| 30 | + | /// Source file extension for binary tests. |
|
| 31 | + | constant SOURCE_EXT: *[u8] = ".rad"; |
|
| 32 | + | /// IL snapshot file extension for binary tests. |
|
| 33 | + | constant SNAPSHOT_EXT: *[u8] = ".ril"; |
|
| 30 | 34 | ||
| 31 | 35 | /// String pool. |
|
| 32 | 36 | static STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 }; |
|
| 33 | 37 | ||
| 34 | 38 | /// Maximum number of AST nodes per test file. |
| 46 | 50 | static PRINT_ARENA_STORAGE: [u8; ARENA_SIZE] = undefined; |
|
| 47 | 51 | static RESOLVER_ARENA_STORAGE: [u8; ARENA_SIZE] = undefined; |
|
| 48 | 52 | static NODE_DATA_STORAGE: [resolver::NodeData; MAX_NODE_DATA] = undefined; |
|
| 49 | 53 | static ERROR_STORAGE: [resolver::Error; MAX_ERRORS] = undefined; |
|
| 50 | 54 | ||
| 51 | - | /// Strip comment from a line. Returns sub-slice up to ';', trimmed of trailing whitespace. |
|
| 55 | + | /// Strip a `//` comment from a line, preserving `//` inside quoted strings. |
|
| 56 | + | /// Returns the content before the comment, trimmed of trailing whitespace. |
|
| 52 | 57 | fn stripLine(line: *[u8]) -> *[u8] { |
|
| 53 | - | let mut end: u32 = 0; |
|
| 58 | + | let mut end = line.len; |
|
| 54 | 59 | let mut i: u32 = 0; |
|
| 60 | + | let mut inString = false; |
|
| 61 | + | let mut escaped = false; |
|
| 55 | 62 | ||
| 56 | - | while i < line.len and line[i] <> ';' { |
|
| 57 | - | if line[i] <> ' ' and line[i] <> '\t' { |
|
| 58 | - | set end = i + 1; |
|
| 63 | + | while i < line.len { |
|
| 64 | + | let ch = line[i]; |
|
| 65 | + | ||
| 66 | + | if inString { |
|
| 67 | + | if escaped { |
|
| 68 | + | set escaped = false; |
|
| 69 | + | } else if ch == '\\' { |
|
| 70 | + | set escaped = true; |
|
| 71 | + | } else if ch == '"' { |
|
| 72 | + | set inString = false; |
|
| 73 | + | } |
|
| 74 | + | } else if ch == '"' { |
|
| 75 | + | set inString = true; |
|
| 76 | + | } else if ch == '/' and i + 1 < line.len and line[i + 1] == '/' { |
|
| 77 | + | set end = i; |
|
| 78 | + | break; |
|
| 59 | 79 | } |
|
| 60 | 80 | set i += 1; |
|
| 61 | 81 | } |
|
| 82 | + | ||
| 83 | + | while end > 0 and (line[end - 1] == ' ' or line[end - 1] == '\t') { |
|
| 84 | + | set end -= 1; |
|
| 85 | + | } |
|
| 62 | 86 | return &line[..end]; |
|
| 63 | 87 | } |
|
| 64 | 88 | ||
| 65 | 89 | /// Get next line from string at offset. Returns the line and updates offset past newline. |
|
| 66 | 90 | fn nextLine(s: *[u8], offset: *mut u32) -> *[u8] { |
| 100 | 124 | return true; |
|
| 101 | 125 | } |
|
| 102 | 126 | ||
| 103 | 127 | /// Print diff between expected and actual output. |
|
| 104 | 128 | fn printDiff(expected: *[u8], actual: *[u8]) { |
|
| 105 | - | io::printLn("\n;; Expected"); |
|
| 129 | + | io::printLn("\n// Expected"); |
|
| 106 | 130 | io::print(expected); |
|
| 107 | 131 | io::print("\n"); |
|
| 108 | 132 | ||
| 109 | - | io::printLn(";; Actual"); |
|
| 133 | + | io::printLn("// Actual"); |
|
| 110 | 134 | io::print(actual); |
|
| 111 | 135 | io::print("\n"); |
|
| 112 | 136 | } |
|
| 113 | 137 | ||
| 114 | 138 | /// Derive the `.ril` path from a `.rad` source path. Returns nil if the path |
|
| 115 | 139 | /// does not end in `.rad` or the buffer is too small. The result is |
|
| 116 | 140 | /// null-terminated for use with syscalls. |
|
| 117 | 141 | fn deriveRilPath(sourcePath: *[u8], buf: *mut [u8]) -> ?*[u8] { |
|
| 118 | 142 | let len = sourcePath.len; |
|
| 119 | - | if len < 4 { |
|
| 143 | + | if len < SOURCE_EXT.len { |
|
| 120 | 144 | return nil; |
|
| 121 | 145 | } |
|
| 146 | + | let extStart = len - SOURCE_EXT.len; |
|
| 122 | 147 | // Check for .rad extension. |
|
| 123 | - | if not mem::eq(&sourcePath[len - 4..len], ".rad") { |
|
| 148 | + | if not mem::eq(&sourcePath[extStart..len], SOURCE_EXT) { |
|
| 124 | 149 | return nil; |
|
| 125 | 150 | } |
|
| 126 | 151 | if len + 1 > buf.len { |
|
| 127 | 152 | return nil; |
|
| 128 | 153 | } |
|
| 129 | 154 | // Copy full path then overwrite extension and add null terminator. |
|
| 130 | 155 | try mem::copy(buf, sourcePath) catch { |
|
| 131 | 156 | return nil; |
|
| 132 | 157 | }; |
|
| 133 | - | // TODO: Rewrite this once we fix the compiler bug and add support for |
|
| 134 | - | // additions in ranges. |
|
| 135 | - | set buf[len - 3] = 'r'; |
|
| 136 | - | set buf[len - 2] = 'i'; |
|
| 137 | - | set buf[len - 1] = 'l'; |
|
| 158 | + | try mem::copy(&mut buf[extStart..len], SNAPSHOT_EXT) catch { |
|
| 159 | + | return nil; |
|
| 160 | + | }; |
|
| 138 | 161 | set buf[len] = 0; |
|
| 139 | 162 | ||
| 140 | 163 | return &buf[..len]; |
|
| 141 | 164 | } |
|
| 142 | 165 |