tests: pending-backend 격리를 없앤다
코드 생성기가 없어서 돌릴 수 없던 것들이다. 이제 돌아간다. 경계 트랩, --no-checks 차등, 슬라이스 범위 검사, 소유권 해제가 전부 exec/ 에서 실행으로 검증되므로 격리할 이유가 없다. run.py 205/205, exec.py 17/17.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
// EXIT:9
|
||||
unit sliceok;
|
||||
|
||||
fn total(s: []i32) -> i32 {
|
||||
var sum: i32 = 0;
|
||||
for v in s { sum = sum + v.^; }
|
||||
return sum;
|
||||
}
|
||||
|
||||
fn main() -> i32 {
|
||||
let a: [5]i32 = [1, 2, 3, 4, 5];
|
||||
let mid: []i32 = a[1..4];
|
||||
return total(mid);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// EXIT:3
|
||||
// OUTPUT:index out of bounds
|
||||
// NOCHECKS:0
|
||||
unit slicerng;
|
||||
|
||||
fn main() -> i32 {
|
||||
let a: [2]i32 = [1, 2];
|
||||
let s: []i32 = a[0..3];
|
||||
let n: i32 = s.n as i32;
|
||||
return n - n;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
`fec/tests/pending-backend/`에 남겨둔 fixture는 현재 프론트엔드 전용 상태에서 실행할 수 없습니다.
|
||||
|
||||
- `bounds_trap.fe` / `bounds_nocheck.fe`: 경계 검사 실패가 실제로 trap되는지,
|
||||
`--no-checks` 플래그가 그 검사를 제거하는지 확인하는 런타임 동작 테스트입니다.
|
||||
- `ownership_drop.fe` + `ownership-drop.c`: 삽입된 `drop`/`defer`가 실제로 실행되는지 확인하는 테스트입니다.
|
||||
`ownership-drop.c`는 해제 횟수/순서/이중 해제를 검증하는 하네스입니다.
|
||||
- `format-prop.c`: 포맷 프로퍼티 동작을 확인하는 런타임 검사입니다.
|
||||
|
||||
이들은 코드 생성기가 없는 현재 단계에서는 실행할 수 없어서 `tests/run.py`가 건너뜁니다.
|
||||
백엔드(코드 생성기)가 돌아오면 가장 먼저 재활성화할 대상입니다.
|
||||
@@ -1,7 +0,0 @@
|
||||
unit m3_no_checks;
|
||||
|
||||
fn main() -> i32 {
|
||||
let a: [2]i32 = [1, 2];
|
||||
let x: i32 = a[2];
|
||||
return x - x;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
unit m3_bounds;
|
||||
|
||||
fn main() -> i32 {
|
||||
let a: [2]i32 = [1, 2];
|
||||
return a[2];
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#include "prop.c"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fe_writer w;
|
||||
unsigned short result;
|
||||
w.tag=2;
|
||||
w.handle=99;
|
||||
result=fe_m4_prop_propagate(w);
|
||||
return result==1 ? 0 : 1;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#undef malloc
|
||||
#undef free
|
||||
|
||||
extern void *malloc(size_t size);
|
||||
extern void free(void *p);
|
||||
|
||||
/* `run` returns !i32, which lowers to { error, value }. */
|
||||
struct fe_result_value_9 { unsigned short e; long v; };
|
||||
extern struct fe_result_value_9 fe_m5_runtime_run(long mode);
|
||||
extern unsigned short fe_m5_runtime_conditional(unsigned char flag);
|
||||
extern unsigned short fe_m5_runtime_argument_cleanup(void);
|
||||
extern unsigned short fe_m5_runtime_owned_slice(unsigned long n);
|
||||
extern unsigned short fe_m5_runtime_replace_field(void);
|
||||
extern unsigned short fe_m5_runtime_loop_cleanup(void);
|
||||
extern unsigned short fe_m5_runtime_try_cleanup(void);
|
||||
extern unsigned short fe_m5_runtime_field_order(void);
|
||||
extern unsigned short fe_m5_runtime_defer_order(void);
|
||||
extern unsigned short fe_m5_runtime_match_cleanup(unsigned char flag);
|
||||
extern unsigned short fe_m5_runtime_close_once(void);
|
||||
extern unsigned short fe_m5_runtime_reassign_struct(void);
|
||||
|
||||
static void *live_ptrs[64];
|
||||
static unsigned live_count;
|
||||
static unsigned alloc_count;
|
||||
static unsigned free_count;
|
||||
static unsigned double_free_count;
|
||||
static long fail_after = -1;
|
||||
static unsigned malloc_attempts;
|
||||
static int track_order;
|
||||
static void *order_ptrs[2];
|
||||
static unsigned order_allocs;
|
||||
static unsigned order_frees;
|
||||
static unsigned order_bad;
|
||||
|
||||
void *m5_malloc(size_t size)
|
||||
{
|
||||
void *p;
|
||||
if (fail_after >= 0 && (long)malloc_attempts++ == fail_after) return 0;
|
||||
p = malloc(size);
|
||||
if (p && live_count < 64) live_ptrs[live_count++] = p;
|
||||
if (p) ++alloc_count;
|
||||
if (p && track_order && order_allocs < 2) order_ptrs[order_allocs++] = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
void m5_free(void *p)
|
||||
{
|
||||
unsigned i;
|
||||
if (!p) return;
|
||||
for (i = 0; i < live_count; ++i) {
|
||||
if (live_ptrs[i] == p) {
|
||||
if (track_order && order_frees < 2 &&
|
||||
p != order_ptrs[1-order_frees]) ++order_bad;
|
||||
if (track_order && order_frees < 2) ++order_frees;
|
||||
live_ptrs[i] = live_ptrs[--live_count];
|
||||
++free_count;
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
++double_free_count;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct fe_result_value_9 r;
|
||||
r = fe_m5_runtime_run(0); if (r.e != 0 || r.v != 0) return 1;
|
||||
r = fe_m5_runtime_run(1); if (r.e != 0 || r.v != 9) return 2;
|
||||
r = fe_m5_runtime_run(2); if (r.e != 0 || r.v != 0) return 3;
|
||||
if (fe_m5_runtime_conditional(0) != 0) return 4;
|
||||
if (fe_m5_runtime_conditional(1) != 0) return 5;
|
||||
if (fe_m5_runtime_argument_cleanup() != 0) return 6;
|
||||
if (fe_m5_runtime_owned_slice(17) != 0) return 7;
|
||||
if (fe_m5_runtime_replace_field() != 0) return 8;
|
||||
if (fe_m5_runtime_loop_cleanup() != 0) return 9;
|
||||
fail_after=1;
|
||||
malloc_attempts=0;
|
||||
if (fe_m5_runtime_try_cleanup() == 0) return 10;
|
||||
fail_after=-1;
|
||||
track_order=1;
|
||||
order_allocs=order_frees=order_bad=0;
|
||||
if (fe_m5_runtime_field_order() != 0) return 11;
|
||||
track_order=0;
|
||||
if (order_allocs != 2 || order_frees != 2 || order_bad != 0) return 12;
|
||||
track_order=1;
|
||||
order_allocs=order_frees=order_bad=0;
|
||||
if (fe_m5_runtime_defer_order() != 0) return 13;
|
||||
track_order=0;
|
||||
if (order_allocs != 2 || order_frees != 2 || order_bad != 0) return 14;
|
||||
if (fe_m5_runtime_match_cleanup(0) != 0) return 15;
|
||||
if (fe_m5_runtime_match_cleanup(1) != 0) return 16;
|
||||
if (fe_m5_runtime_close_once() != 0) return 17;
|
||||
if (fe_m5_runtime_reassign_struct() != 0) return 18;
|
||||
if (double_free_count != 0) return 19;
|
||||
if (live_count != 0) return 20;
|
||||
if (alloc_count != free_count) return 21;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
unit m5_runtime;
|
||||
|
||||
fn take(p: ^i32) -> void { mem.destroy(p); }
|
||||
|
||||
pub fn run(mode: i32) -> !i32 {
|
||||
var p: ^i32 = try mem.create(0);
|
||||
defer { mem.destroy(p); }
|
||||
p.^ = 7;
|
||||
if mode == 1 {
|
||||
p = try mem.create(0);
|
||||
p.^ = 9;
|
||||
return p.^;
|
||||
}
|
||||
while true { break; }
|
||||
if mode == 2 { return 0; }
|
||||
return p.^ - 7;
|
||||
}
|
||||
|
||||
pub fn conditional(flag: bool) -> !void {
|
||||
var p: ^i32 = try mem.create(0);
|
||||
if flag { take(p); }
|
||||
}
|
||||
|
||||
pub fn argument_cleanup() -> !void {
|
||||
let p: ^i32 = try mem.create(0);
|
||||
take(p);
|
||||
}
|
||||
|
||||
pub fn owned_slice(n: usize) -> !void {
|
||||
let bytes: ^[]u8 = try mem.alloc_slice(u8, n);
|
||||
}
|
||||
|
||||
struct Holder { p: ^i32 }
|
||||
|
||||
pub fn replace_field() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
var h: Holder = Holder{ p: first };
|
||||
let second: ^i32 = try mem.create(2);
|
||||
let old: ^i32 = mem.replace(&mut h.p, second);
|
||||
mem.destroy(old);
|
||||
}
|
||||
|
||||
pub fn loop_cleanup() -> !void {
|
||||
var i: i32 = 0;
|
||||
while i < 2 {
|
||||
let p: ^i32 = try mem.create(i);
|
||||
i += 1;
|
||||
if i == 1 { continue; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_cleanup() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
let second: ^i32 = try mem.create(2);
|
||||
}
|
||||
|
||||
struct PairOwners { first: ^i32, second: ^i32 }
|
||||
|
||||
pub fn field_order() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
let second: ^i32 = try mem.create(2);
|
||||
let pair: PairOwners = PairOwners{ first: first, second: second };
|
||||
}
|
||||
|
||||
pub fn defer_order() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
defer { mem.destroy(first); }
|
||||
let second: ^i32 = try mem.create(2);
|
||||
}
|
||||
|
||||
enum Choice { A, B }
|
||||
|
||||
pub fn match_cleanup(flag: bool) -> !void {
|
||||
var choice: Choice = Choice.A;
|
||||
if flag { choice = Choice.B; }
|
||||
let p: ^i32 = try mem.create(1);
|
||||
match choice {
|
||||
A => { take(p); }
|
||||
B => { take(p); }
|
||||
}
|
||||
}
|
||||
|
||||
struct FileLike {
|
||||
handle: i32,
|
||||
fn close(self: Self) -> !void { self.handle = 0; }
|
||||
fn drop(self: &mut Self) { self.handle = 0; }
|
||||
}
|
||||
|
||||
pub fn close_once() -> !void {
|
||||
let file: FileLike = FileLike{ handle: 7 };
|
||||
try file.close();
|
||||
}
|
||||
|
||||
pub fn reassign_struct() -> !void {
|
||||
let first: ^i32 = try mem.create(1);
|
||||
var owner: Holder = Holder{ p: first };
|
||||
let second: ^i32 = try mem.create(2);
|
||||
owner = Holder{ p: second };
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
unit m3_slice_bounds;
|
||||
|
||||
fn main() -> i32 {
|
||||
let a: [2]i32 = [1, 2];
|
||||
let s: []i32 = a[0..3];
|
||||
return s.n as i32;
|
||||
}
|
||||
Reference in New Issue
Block a user