2014-10-30 15 views
5

Tôi đang viết một số mã Rust xử lý các con trỏ thô. Những con trỏ thô sau đó được tiếp xúc với người dùng thông qua các cấu trúc sử dụng ContravariantLifetime để gắn kết vòng đời của cấu trúc với đối tượng của tôi.Tôi có thể viết các bài kiểm tra cho các kiếp sống không hợp lệ không?

Tôi muốn có thể viết các bài kiểm tra xác thực rằng cấu trúc người dùng không thể sống lâu hơn đối tượng của tôi. Tôi có mã như sau:

fn element_cannot_outlive_parts() { 
    let mut z = { 
     let p = Package::new(); 
     p.create() // returns an object that cannot live longer than p 
    }; 
} 

Điều này không biên dịch, chính xác là những gì tôi muốn. Tuy nhiên, tôi muốn có một số kiểm tra tự động rằng hành vi này là đúng ngay cả sau khi bất kỳ refactoring tôi làm gì để mã. Ý tưởng tốt nhất của tôi vào lúc này là viết các tệp Rust một lần với mã này và tạo các tập lệnh bash để cố gắng biên dịch chúng và tìm kiếm các thông báo lỗi cụ thể, tất cả đều cảm thấy khá khó khăn.

+4

Than ôi, không có hỗ trợ gốc cho các bài kiểm tra không biên soạn. Bản thân rustc có cơ sở hạ tầng để đạt được điều này ('src/test/compile-fail' et al.), nhưng nó là tùy chỉnh và thường không có sẵn. –

+0

@ ChrisMorgan: Bạn có tin rằng sẽ có sự quan tâm trong cộng đồng để hỗ trợ cho loại thử nghiệm này không? Rust có một hệ thống kiểu thực sự phát triển cho phép thực thi rất nhiều kiểm tra, và có vẻ tốt để xác minh rằng các kiểm tra thực sự được thực thi. Trong quá khứ, với C++, tôi đã sử dụng các bài kiểm tra cụ thể của Clang ('-verify' flag + các bình luận cụ thể của Clang) cho loại điều này; nó khá tiên tiến. –

+0

@MatthieuM .: Tôi biết rằng tôi muốn có khả năng, khi thiết kế một thư viện, có các bài kiểm tra xác minh rằng mã nhất định không biên dịch. –

Trả lời

1

Dự án Rust có một bộ kiểm tra đặc biệt gọi là "biên dịch không thành công" kiểm tra thực hiện chính xác những gì bạn muốn.

Các compiletest crate là một chiết xuất của ý tưởng này cho phép các thư viện khác để làm điều tương tự:

fn main() { 
    let x: (u64, bool) = (true, 42u64); 
    //~^ ERROR mismatched types 
    //~^^ ERROR mismatched types 
} 

Một ý tưởng đó được nửa đường là sử dụng của hàng hóa "tính năng".

Chỉ định xét nghiệm với một tính năng cờ:

#[test] 
#[cfg(feature = "compile_failure")] 
fn bogus_test() {} 

Thêm phần này vào Cargo.toml:

[features] 

compile_failure = [] 

Và kiểm tra chạy như

cargo test --features compile_failure 

Điều hiển nhiên mất tích từ này là việc kiểm tra tự động "đó có phải là lỗi đúng không". Nếu không có gì khác, điều này cho phép tôi có các bài kiểm tra được bán trong codebase của tôi.

-2

Bạn có thể chú thích một bài kiểm tra mà bạn mong đợi không thành công.

#[should_fail] 

Như vậy, bạn có thể viết một thử nghiệm cố gắng vi phạm thời gian sống cần thiết, và do đó không thực sự vượt qua được.

Đối với một ví dụ về một thử nghiệm cho 'chỉ số nằm ngoài giới hạn' xem dưới đây (kéo từ Rust guides)

#[test] 
#[should_fail] 
fn test_out_of_bounds_failure() { 
    let v: &[int] = []; 
    v[0]; 
} 

Tôi tin rằng ví dụ này sẽ là một lỗi biên dịch, vì vậy nó sẽ đứng để lý do của bạn biên dịch lỗi vi phạm suốt đời sẽ bị bắt bởi điều này quá.

+0

'# [should_fail]' là do lỗi thời gian chạy (bây giờ được gọi là "panics"), không phải cho các lỗi biên dịch. –

+0

Có lẽ chúng ta cần đẩy một '# [should_fail_compile]' (bán nghiêm túc) – thecoshman

Các vấn đề liên quan