<commit_before>extern crate reqwest;
extern crate libflate;

#[macro_use] mod server;

use std::io::Read;
use std::io::prelude::*;

#[test]
fn test_get() {
    let server = server! {
        request: b"\
            GET /1 HTTP/1.1\r\n\
            Host: $HOST\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 200 OK\r\n\
            Server: test\r\n\
            Content-Length: 0\r\n\
            \r\n\
            "
    };

    let mut res = reqwest::get(&format!("http://{}/1", server.addr())).unwrap();
    assert_eq!(res.status(), &reqwest::StatusCode::Ok);
    assert_eq!(res.version(), &reqwest::HttpVersion::Http11);
    assert_eq!(res.headers().get(), Some(&reqwest::header::Server("test".to_string())));
    assert_eq!(res.headers().get(), Some(&reqwest::header::ContentLength(0)));

    let mut buf = [0; 1024];
    let n = res.read(&mut buf).unwrap();
    assert_eq!(n, 0)
}

#[test]
fn test_redirect_301_and_302_and_303_changes_post_to_get() {
    let client = reqwest::Client::new().unwrap();
    let codes = [301, 302, 303];

    for code in codes.iter() {
        let redirect = server! {
            request: format!("\
                POST /{} HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Content-Length: 0\r\n\
                \r\n\
                ", code),
            response: format!("\
                HTTP/1.1 {} reason\r\n\
                Server: test-redirect\r\n\
                Content-Length: 0\r\n\
                Location: /dst\r\n\
                Connection: close\r\n\
                \r\n\
                ", code),

            request: format!("\
                GET /dst HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Referer: http://$HOST/{}\r\n\
                \r\n\
                ", code),
            response: b"\
                HTTP/1.1 200 OK\r\n\
                Server: test-dst\r\n\
                Content-Length: 0\r\n\
                \r\n\
                "
        };

        let res = client.post(&format!("http://{}/{}", redirect.addr(), code))
            .send()
            .unwrap();
        assert_eq!(res.status(), &reqwest::StatusCode::Ok);
        assert_eq!(res.headers().get(), Some(&reqwest::header::Server("test-dst".to_string())));
    }
}

#[test]
fn test_redirect_307_and_308_tries_to_post_again() {
    let client = reqwest::Client::new().unwrap();
    let codes = [307, 308];
    for code in codes.iter() {
        let redirect = server! {
            request: format!("\
                POST /{} HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Content-Length: 5\r\n\
                \r\n\
                Hello\
                ", code),
            response: format!("\
                HTTP/1.1 {} reason\r\n\
                Server: test-redirect\r\n\
                Content-Length: 0\r\n\
                Location: /dst\r\n\
                Connection: close\r\n\
                \r\n\
                ", code),

            request: format!("\
                POST /dst HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Referer: http://$HOST/{}\r\n\
                Content-Length: 5\r\n\
                \r\n\
                Hello\
                ", code),
            response: b"\
                HTTP/1.1 200 OK\r\n\
                Server: test-dst\r\n\
                Content-Length: 0\r\n\
                \r\n\
                "
        };

        let res = client.post(&format!("http://{}/{}", redirect.addr(), code))
            .body("Hello")
            .send()
            .unwrap();
        assert_eq!(res.status(), &reqwest::StatusCode::Ok);
        assert_eq!(res.headers().get(), Some(&reqwest::header::Server("test-dst".to_string())));
    }
}

#[test]
fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
    let client = reqwest::Client::new().unwrap();
    let codes = [307, 308];
    for &code in codes.iter() {
        let redirect = server! {
            request: format!("\
                POST /{} HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Transfer-Encoding: chunked\r\n\
                \r\n\
                5\r\n\
                Hello\r\n\
                0\r\n\r\n\
                ", code),
            response: format!("\
                HTTP/1.1 {} reason\r\n\
                Server: test-redirect\r\n\
                Content-Length: 0\r\n\
                Location: /dst\r\n\
                Connection: close\r\n\
                \r\n\
                ", code)
        };

        let res = client.post(&format!("http://{}/{}", redirect.addr(), code))
            .body(reqwest::Body::new(&b"Hello"[..]))
            .send()
            .unwrap();
        assert_eq!(res.status(), &reqwest::StatusCode::from_u16(code));
    }
}

#[test]
fn test_redirect_policy_can_return_errors() {
    let server = server! {
        request: b"\
            GET /loop HTTP/1.1\r\n\
            Host: $HOST\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 302 Found\r\n\
            Server: test\r\n\
            Location: /loop
            Content-Length: 0\r\n\
            \r\n\
            "
    };

    let err = reqwest::get(&format!("http://{}/loop", server.addr())).unwrap_err();
    match err {
        reqwest::Error::RedirectLoop => (),
        e => panic!("wrong error received: {:?}", e),
    }
}

#[test]
fn test_redirect_policy_can_stop_redirects_without_an_error() {
    let server = server! {
        request: b"\
            GET /no-redirect HTTP/1.1\r\n\
            Host: $HOST\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 302 Found\r\n\
            Server: test-dont\r\n\
            Location: /dont
            Content-Length: 0\r\n\
            \r\n\
            "
    };
    let mut client = reqwest::Client::new().unwrap();
    client.redirect(reqwest::RedirectPolicy::none());

    let res = client.get(&format!("http://{}/no-redirect", server.addr()))
        .send()
        .unwrap();

    assert_eq!(res.status(), &reqwest::StatusCode::Found);
    assert_eq!(res.headers().get(), Some(&reqwest::header::Server("test-dont".to_string())));
}

#[test]
fn test_accept_header_is_not_changed_if_set() {
    let server = server! {
        request: b"\
            GET /accept HTTP/1.1\r\n\
            Host: $HOST\r\n\
            Accept: application/json\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 200 OK\r\n\
            Server: test-accept\r\n\
            Content-Length: 0\r\n\
            \r\n\
            "
    };
    let client = reqwest::Client::new().unwrap();

    let res = client.get(&format!("http://{}/accept", server.addr()))
        .header(reqwest::header::Accept::json())
        .send()
        .unwrap();

    assert_eq!(res.status(), &reqwest::StatusCode::Ok);
}

#[test]
fn test_accept_encoding_header_is_not_changed_if_set() {
    let server = server! {
        request: b"\
            GET /accept-encoding HTTP/1.1\r\n\
            Host: $HOST\r\n\
            Accept-Encoding: identity\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 200 OK\r\n\
            Server: test-accept-encoding\r\n\
            Content-Length: 0\r\n\
            \r\n\
            "
    };
    let client = reqwest::Client::new().unwrap();

    let res = client.get(&format!("http://{}/accept-encoding", server.addr()))
        .header(reqwest::header::AcceptEncoding(
            vec![reqwest::header::qitem(reqwest::header::Encoding::Identity)]
        ))
        .send()
        .unwrap();

    assert_eq!(res.status(), &reqwest::StatusCode::Ok);
}

#[test]
fn test_gzip_response() {
    let mut encoder = ::libflate::gzip::Encoder::new(Vec::new()).unwrap();
    match encoder.write(b"test request") {
        Ok(n) => assert!(n > 0, "Failed to write to encoder."),
        _ => panic!("Failed to gzip encode string.")
    };

    let gzipped_content = encoder.finish().into_result().unwrap();

    let mut response = format!("\
            HTTP/1.1 200 OK\r\n\
            Server: test-accept\r\n\
            Content-Encoding: gzip\r\n\
            Content-Length: {}\r\n\
            \r\n", &gzipped_content.len())
        .into_bytes();
    response.extend(&gzipped_content);

    let server = server! {
        request: b"\
            GET /gzip HTTP/1.1\r\n\
            Host: $HOST\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: response
    };
    let mut res = reqwest::get(&format!("http://{}/gzip", server.addr()))
        .unwrap();

    let mut body = ::std::string::String::new();
    match res.read_to_string(&mut body) {
        Ok(n) => assert!(n > 0, "Failed to write to buffer."),
        _ => panic!("Failed to write to buffer.")
    };

    assert_eq!(body, "test request");
}
<commit_msg>Add test for response' final URL<commit_after>extern crate reqwest;
extern crate libflate;

#[macro_use] mod server;

use std::io::Read;
use std::io::prelude::*;

#[test]
fn test_get() {
    let server = server! {
        request: b"\
            GET /1 HTTP/1.1\r\n\
            Host: $HOST\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 200 OK\r\n\
            Server: test\r\n\
            Content-Length: 0\r\n\
            \r\n\
            "
    };

    let url = format!("http://{}/1", server.addr());
    let mut res = reqwest::get(&url).unwrap();

    assert_eq!(res.url().as_str(), &url);
    assert_eq!(res.status(), &reqwest::StatusCode::Ok);
    assert_eq!(res.version(), &reqwest::HttpVersion::Http11);
    assert_eq!(res.headers().get(), Some(&reqwest::header::Server("test".to_string())));
    assert_eq!(res.headers().get(), Some(&reqwest::header::ContentLength(0)));

    let mut buf = [0; 1024];
    let n = res.read(&mut buf).unwrap();
    assert_eq!(n, 0)
}

#[test]
fn test_redirect_301_and_302_and_303_changes_post_to_get() {
    let client = reqwest::Client::new().unwrap();
    let codes = [301, 302, 303];

    for code in codes.iter() {
        let redirect = server! {
            request: format!("\
                POST /{} HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Content-Length: 0\r\n\
                \r\n\
                ", code),
            response: format!("\
                HTTP/1.1 {} reason\r\n\
                Server: test-redirect\r\n\
                Content-Length: 0\r\n\
                Location: /dst\r\n\
                Connection: close\r\n\
                \r\n\
                ", code),

            request: format!("\
                GET /dst HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Referer: http://$HOST/{}\r\n\
                \r\n\
                ", code),
            response: b"\
                HTTP/1.1 200 OK\r\n\
                Server: test-dst\r\n\
                Content-Length: 0\r\n\
                \r\n\
                "
        };

        let url = format!("http://{}/{}", redirect.addr(), code);
        let dst = format!("http://{}/{}", redirect.addr(), "dst");
        let res = client.post(&url)
            .send()
            .unwrap();
        assert_eq!(res.url().as_str(), dst);
        assert_eq!(res.status(), &reqwest::StatusCode::Ok);
        assert_eq!(res.headers().get(), Some(&reqwest::header::Server("test-dst".to_string())));
    }
}

#[test]
fn test_redirect_307_and_308_tries_to_post_again() {
    let client = reqwest::Client::new().unwrap();
    let codes = [307, 308];
    for code in codes.iter() {
        let redirect = server! {
            request: format!("\
                POST /{} HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Content-Length: 5\r\n\
                \r\n\
                Hello\
                ", code),
            response: format!("\
                HTTP/1.1 {} reason\r\n\
                Server: test-redirect\r\n\
                Content-Length: 0\r\n\
                Location: /dst\r\n\
                Connection: close\r\n\
                \r\n\
                ", code),

            request: format!("\
                POST /dst HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Referer: http://$HOST/{}\r\n\
                Content-Length: 5\r\n\
                \r\n\
                Hello\
                ", code),
            response: b"\
                HTTP/1.1 200 OK\r\n\
                Server: test-dst\r\n\
                Content-Length: 0\r\n\
                \r\n\
                "
        };

        let url = format!("http://{}/{}", redirect.addr(), code);
        let dst = format!("http://{}/{}", redirect.addr(), "dst");
        let res = client.post(&url)
            .body("Hello")
            .send()
            .unwrap();
        assert_eq!(res.url().as_str(), dst);
        assert_eq!(res.status(), &reqwest::StatusCode::Ok);
        assert_eq!(res.headers().get(), Some(&reqwest::header::Server("test-dst".to_string())));
    }
}

#[test]
fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
    let client = reqwest::Client::new().unwrap();
    let codes = [307, 308];
    for &code in codes.iter() {
        let redirect = server! {
            request: format!("\
                POST /{} HTTP/1.1\r\n\
                Host: $HOST\r\n\
                User-Agent: $USERAGENT\r\n\
                Accept: */*\r\n\
                Accept-Encoding: gzip\r\n\
                Transfer-Encoding: chunked\r\n\
                \r\n\
                5\r\n\
                Hello\r\n\
                0\r\n\r\n\
                ", code),
            response: format!("\
                HTTP/1.1 {} reason\r\n\
                Server: test-redirect\r\n\
                Content-Length: 0\r\n\
                Location: /dst\r\n\
                Connection: close\r\n\
                \r\n\
                ", code)
        };

        let url = format!("http://{}/{}", redirect.addr(), code);
        let res = client.post(&url)
            .body(reqwest::Body::new(&b"Hello"[..]))
            .send()
            .unwrap();
        assert_eq!(res.url().as_str(), url);
        assert_eq!(res.status(), &reqwest::StatusCode::from_u16(code));
    }
}

#[test]
fn test_redirect_policy_can_return_errors() {
    let server = server! {
        request: b"\
            GET /loop HTTP/1.1\r\n\
            Host: $HOST\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 302 Found\r\n\
            Server: test\r\n\
            Location: /loop
            Content-Length: 0\r\n\
            \r\n\
            "
    };

    let err = reqwest::get(&format!("http://{}/loop", server.addr())).unwrap_err();
    match err {
        reqwest::Error::RedirectLoop => (),
        e => panic!("wrong error received: {:?}", e),
    }
}

#[test]
fn test_redirect_policy_can_stop_redirects_without_an_error() {
    let server = server! {
        request: b"\
            GET /no-redirect HTTP/1.1\r\n\
            Host: $HOST\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 302 Found\r\n\
            Server: test-dont\r\n\
            Location: /dont
            Content-Length: 0\r\n\
            \r\n\
            "
    };
    let mut client = reqwest::Client::new().unwrap();
    client.redirect(reqwest::RedirectPolicy::none());

    let url = format!("http://{}/no-redirect", server.addr());
    let res = client.get(&url)
        .send()
        .unwrap();

    assert_eq!(res.url().as_str(), url);
    assert_eq!(res.status(), &reqwest::StatusCode::Found);
    assert_eq!(res.headers().get(), Some(&reqwest::header::Server("test-dont".to_string())));
}

#[test]
fn test_accept_header_is_not_changed_if_set() {
    let server = server! {
        request: b"\
            GET /accept HTTP/1.1\r\n\
            Host: $HOST\r\n\
            Accept: application/json\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 200 OK\r\n\
            Server: test-accept\r\n\
            Content-Length: 0\r\n\
            \r\n\
            "
    };
    let client = reqwest::Client::new().unwrap();

    let res = client.get(&format!("http://{}/accept", server.addr()))
        .header(reqwest::header::Accept::json())
        .send()
        .unwrap();

    assert_eq!(res.status(), &reqwest::StatusCode::Ok);
}

#[test]
fn test_accept_encoding_header_is_not_changed_if_set() {
    let server = server! {
        request: b"\
            GET /accept-encoding HTTP/1.1\r\n\
            Host: $HOST\r\n\
            Accept-Encoding: identity\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            \r\n\
            ",
        response: b"\
            HTTP/1.1 200 OK\r\n\
            Server: test-accept-encoding\r\n\
            Content-Length: 0\r\n\
            \r\n\
            "
    };
    let client = reqwest::Client::new().unwrap();

    let res = client.get(&format!("http://{}/accept-encoding", server.addr()))
        .header(reqwest::header::AcceptEncoding(
            vec![reqwest::header::qitem(reqwest::header::Encoding::Identity)]
        ))
        .send()
        .unwrap();

    assert_eq!(res.status(), &reqwest::StatusCode::Ok);
}

#[test]
fn test_gzip_response() {
    let mut encoder = ::libflate::gzip::Encoder::new(Vec::new()).unwrap();
    match encoder.write(b"test request") {
        Ok(n) => assert!(n > 0, "Failed to write to encoder."),
        _ => panic!("Failed to gzip encode string.")
    };

    let gzipped_content = encoder.finish().into_result().unwrap();

    let mut response = format!("\
            HTTP/1.1 200 OK\r\n\
            Server: test-accept\r\n\
            Content-Encoding: gzip\r\n\
            Content-Length: {}\r\n\
            \r\n", &gzipped_content.len())
        .into_bytes();
    response.extend(&gzipped_content);

    let server = server! {
        request: b"\
            GET /gzip HTTP/1.1\r\n\
            Host: $HOST\r\n\
            User-Agent: $USERAGENT\r\n\
            Accept: */*\r\n\
            Accept-Encoding: gzip\r\n\
            \r\n\
            ",
        response: response
    };
    let mut res = reqwest::get(&format!("http://{}/gzip", server.addr()))
        .unwrap();

    let mut body = ::std::string::String::new();
    match res.read_to_string(&mut body) {
        Ok(n) => assert!(n > 0, "Failed to write to buffer."),
        _ => panic!("Failed to write to buffer.")
    };

    assert_eq!(body, "test request");
}
<|endoftext|>


<commit_before>//! Translation skeletton that traverses the whole WebAssembly module and call helper functions
//! to deal with each part of it.
use cretonne::timing;
use wasmparser::{ParserState, SectionCode, ParserInput, Parser, WasmDecoder, BinaryReaderError};
use sections_translator::{SectionParsingError, parse_function_signatures, parse_import_section,
                          parse_function_section, parse_export_section, parse_start_section,
                          parse_memory_section, parse_global_section, parse_table_section,
                          parse_elements_section, parse_data_section};
use environ::ModuleEnvironment;

/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL
/// [`Function`](../cretonne/ir/function/struct.Function.html).
/// Returns the functions and also the mappings for imported functions and signature between the
/// indexes in the wasm module and the indexes inside each functions.
pub fn translate_module<'data>(
    data: &'data [u8],
    environ: &mut ModuleEnvironment<'data>,
) -> Result<(), String> {
    let _tt = timing::wasm_translate_module();
    let mut parser = Parser::new(data);
    match *parser.read() {
        ParserState::BeginWasm { .. } => {}
        ParserState::Error(BinaryReaderError { message, offset }) => {
            return Err(format!("at offset {}: {}", offset, message));
        }
        ref s => panic!("modules should begin properly: {:?}", s),
    }
    let mut next_input = ParserInput::Default;
    loop {
        match *parser.read_with_input(next_input) {
            ParserState::BeginSection { code: SectionCode::Type, .. } => {
                match parse_function_signatures(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the type section: {}", s))
                    }
                };
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Import, .. } => {
                match parse_import_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the import section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Function, .. } => {
                match parse_function_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the function section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Table, .. } => {
                match parse_table_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the table section: {}", s))
                    }
                }
            }
            ParserState::BeginSection { code: SectionCode::Memory, .. } => {
                match parse_memory_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the memory section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Global, .. } => {
                match parse_global_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the global section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Export, .. } => {
                match parse_export_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the export section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Start, .. } => {
                match parse_start_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the start section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Element, .. } => {
                match parse_elements_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the element section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Code, .. } => {
                // The code section begins
                break;
            }
            ParserState::EndSection => {
                next_input = ParserInput::Default;
            }
            ParserState::EndWasm => return Ok(()),
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            _ => return Err(String::from("wrong content in the preamble")),
        };
    }
    // At this point we've entered the code section
    loop {
        match *parser.read() {
            ParserState::BeginFunctionBody { .. } => {}
            ParserState::EndSection => break,
            _ => return Err(String::from("wrong content in code section")),
        }
        let mut reader = parser.create_binary_reader();
        let size = reader.bytes_remaining();
        environ.define_function_body(
            reader.read_bytes(size).map_err(|e| {
                format!("at offset {}: {}", e.offset, e.message)
            })?,
        )?;
    }
    loop {
        match *parser.read() {
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            ParserState::EndWasm => break,
            _ => (),
        }
    }
    Ok(())
}
<commit_msg>Ignore unknown custom wasm sections.<commit_after>//! Translation skeletton that traverses the whole WebAssembly module and call helper functions
//! to deal with each part of it.
use cretonne::timing;
use wasmparser::{ParserState, SectionCode, ParserInput, Parser, WasmDecoder, BinaryReaderError};
use sections_translator::{SectionParsingError, parse_function_signatures, parse_import_section,
                          parse_function_section, parse_export_section, parse_start_section,
                          parse_memory_section, parse_global_section, parse_table_section,
                          parse_elements_section, parse_data_section};
use environ::ModuleEnvironment;

/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL
/// [`Function`](../cretonne/ir/function/struct.Function.html).
/// Returns the functions and also the mappings for imported functions and signature between the
/// indexes in the wasm module and the indexes inside each functions.
pub fn translate_module<'data>(
    data: &'data [u8],
    environ: &mut ModuleEnvironment<'data>,
) -> Result<(), String> {
    let _tt = timing::wasm_translate_module();
    let mut parser = Parser::new(data);
    match *parser.read() {
        ParserState::BeginWasm { .. } => {}
        ParserState::Error(BinaryReaderError { message, offset }) => {
            return Err(format!("at offset {}: {}", offset, message));
        }
        ref s => panic!("modules should begin properly: {:?}", s),
    }
    let mut next_input = ParserInput::Default;
    loop {
        match *parser.read_with_input(next_input) {
            ParserState::BeginSection { code: SectionCode::Type, .. } => {
                match parse_function_signatures(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the type section: {}", s))
                    }
                };
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Import, .. } => {
                match parse_import_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the import section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Function, .. } => {
                match parse_function_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the function section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Table, .. } => {
                match parse_table_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the table section: {}", s))
                    }
                }
            }
            ParserState::BeginSection { code: SectionCode::Memory, .. } => {
                match parse_memory_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the memory section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Global, .. } => {
                match parse_global_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the global section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Export, .. } => {
                match parse_export_section(&mut parser, environ) {
                    Ok(()) => {}
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the export section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Start, .. } => {
                match parse_start_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the start section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Element, .. } => {
                match parse_elements_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the element section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Code, .. } => {
                // The code section begins
                break;
            }
            ParserState::EndSection => {
                next_input = ParserInput::Default;
            }
            ParserState::EndWasm => return Ok(()),
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            ParserState::BeginSection { code: SectionCode::Custom { .. }, .. } => {
                // Ignore unknown custom sections.
                next_input = ParserInput::SkipSection;
            }
            _ => return Err(String::from("wrong content in the preamble")),
        };
    }
    // At this point we've entered the code section
    loop {
        match *parser.read() {
            ParserState::BeginFunctionBody { .. } => {}
            ParserState::EndSection => break,
            _ => return Err(String::from("wrong content in code section")),
        }
        let mut reader = parser.create_binary_reader();
        let size = reader.bytes_remaining();
        environ.define_function_body(
            reader.read_bytes(size).map_err(|e| {
                format!("at offset {}: {}", e.offset, e.message)
            })?,
        )?;
    }
    loop {
        match *parser.read() {
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, environ) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            ParserState::EndWasm => break,
            _ => (),
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! LLVM diagnostic reports.

pub use self::OptimizationDiagnosticKind::*;
pub use self::Diagnostic::*;

use libc::{c_char, c_uint};
use std::ptr;

use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef};

#[derive(Copy, Clone)]
pub enum OptimizationDiagnosticKind {
    OptimizationRemark,
    OptimizationMissed,
    OptimizationAnalysis,
    OptimizationFailure,
}

impl OptimizationDiagnosticKind {
    pub fn describe(self) -> &'static str {
        match self {
            OptimizationRemark => "remark",
            OptimizationMissed => "missed",
            OptimizationAnalysis => "analysis",
            OptimizationFailure => "failure",
        }
    }
}

#[derive(Copy, Clone)]
pub struct OptimizationDiagnostic {
    pub kind: OptimizationDiagnosticKind,
    pub pass_name: *const c_char,
    pub function: ValueRef,
    pub debug_loc: DebugLocRef,
    pub message: TwineRef,
}

impl OptimizationDiagnostic {
    unsafe fn unpack(kind: OptimizationDiagnosticKind, di: DiagnosticInfoRef)
            -> OptimizationDiagnostic {

        let mut opt = OptimizationDiagnostic {
            kind: kind,
            pass_name: ptr::null(),
            function: ptr::null_mut(),
            debug_loc: ptr::null_mut(),
            message: ptr::null_mut(),
        };

        super::LLVMUnpackOptimizationDiagnostic(di,
            &mut opt.pass_name,
            &mut opt.function,
            &mut opt.debug_loc,
            &mut opt.message);

        opt
    }
}

#[derive(Copy, Clone)]
pub struct InlineAsmDiagnostic {
    pub cookie: c_uint,
    pub message: TwineRef,
    pub instruction: ValueRef,
}

impl InlineAsmDiagnostic {
    unsafe fn unpack(di: DiagnosticInfoRef)
            -> InlineAsmDiagnostic {

        let mut opt = InlineAsmDiagnostic {
            cookie: 0,
            message: ptr::null_mut(),
            instruction: ptr::null_mut(),
        };

        super::LLVMUnpackInlineAsmDiagnostic(di,
            &mut opt.cookie,
            &mut opt.message,
            &mut opt.instruction);

        opt
    }
}

#[derive(Copy, Clone)]
pub enum Diagnostic {
    Optimization(OptimizationDiagnostic),
    InlineAsm(InlineAsmDiagnostic),

    /// LLVM has other types that we do not wrap here.
    UnknownDiagnostic(DiagnosticInfoRef),
}

impl Diagnostic {
    pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic {
        let kind = super::LLVMGetDiagInfoKind(di);

        match kind {
            super::DK_InlineAsm
                => InlineAsm(InlineAsmDiagnostic::unpack(di)),

            super::DK_OptimizationRemark
                => Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)),

            super::DK_OptimizationRemarkMissed
                => Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di)),

            super::DK_OptimizationRemarkAnalysis
                => Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di)),

            super::DK_OptimizationFailure
                => Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)),

            _ => UnknownDiagnostic(di)
        }
    }
}
<commit_msg>Rollup merge of #29933 - tbu-:pr_dont_opt_in_copy, r=nikomatsakis<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! LLVM diagnostic reports.

pub use self::OptimizationDiagnosticKind::*;
pub use self::Diagnostic::*;

use libc::{c_char, c_uint};
use std::ptr;

use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef};

#[derive(Copy, Clone)]
pub enum OptimizationDiagnosticKind {
    OptimizationRemark,
    OptimizationMissed,
    OptimizationAnalysis,
    OptimizationFailure,
}

impl OptimizationDiagnosticKind {
    pub fn describe(self) -> &'static str {
        match self {
            OptimizationRemark => "remark",
            OptimizationMissed => "missed",
            OptimizationAnalysis => "analysis",
            OptimizationFailure => "failure",
        }
    }
}

pub struct OptimizationDiagnostic {
    pub kind: OptimizationDiagnosticKind,
    pub pass_name: *const c_char,
    pub function: ValueRef,
    pub debug_loc: DebugLocRef,
    pub message: TwineRef,
}

impl OptimizationDiagnostic {
    unsafe fn unpack(kind: OptimizationDiagnosticKind, di: DiagnosticInfoRef)
            -> OptimizationDiagnostic {

        let mut opt = OptimizationDiagnostic {
            kind: kind,
            pass_name: ptr::null(),
            function: ptr::null_mut(),
            debug_loc: ptr::null_mut(),
            message: ptr::null_mut(),
        };

        super::LLVMUnpackOptimizationDiagnostic(di,
            &mut opt.pass_name,
            &mut opt.function,
            &mut opt.debug_loc,
            &mut opt.message);

        opt
    }
}

#[derive(Copy, Clone)]
pub struct InlineAsmDiagnostic {
    pub cookie: c_uint,
    pub message: TwineRef,
    pub instruction: ValueRef,
}

impl InlineAsmDiagnostic {
    unsafe fn unpack(di: DiagnosticInfoRef)
            -> InlineAsmDiagnostic {

        let mut opt = InlineAsmDiagnostic {
            cookie: 0,
            message: ptr::null_mut(),
            instruction: ptr::null_mut(),
        };

        super::LLVMUnpackInlineAsmDiagnostic(di,
            &mut opt.cookie,
            &mut opt.message,
            &mut opt.instruction);

        opt
    }
}

pub enum Diagnostic {
    Optimization(OptimizationDiagnostic),
    InlineAsm(InlineAsmDiagnostic),

    /// LLVM has other types that we do not wrap here.
    UnknownDiagnostic(DiagnosticInfoRef),
}

impl Diagnostic {
    pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic {
        let kind = super::LLVMGetDiagInfoKind(di);

        match kind {
            super::DK_InlineAsm
                => InlineAsm(InlineAsmDiagnostic::unpack(di)),

            super::DK_OptimizationRemark
                => Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)),

            super::DK_OptimizationRemarkMissed
                => Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di)),

            super::DK_OptimizationRemarkAnalysis
                => Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di)),

            super::DK_OptimizationFailure
                => Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)),

            _ => UnknownDiagnostic(di)
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate adapton;

mod engine_is_from_scratch_consistent {
    //! This module tests that change propagation is from-scratch consistent

    /// Compare to this sound behavior to the unsound behavior from
    /// JaneStreet 'Incremental' libary.  In particular, Yit's gist
    /// shows the problematic change propagation behavior:
    /// https://gist.github.com/khooyp/98abc0e64dc296deaa48
    #[test]
    fn test1 () {

        use std::rc::Rc;
        use adapton::macros::*;
        use adapton::engine::*;
        manage::init_dcg();

        // Construct two mutable inputs, `nom` and `den`, a
        // computation `div` that divides the nominator in `nom` by
        // the denominator in `den`, and a root thunk `t` that first
        // checks whether the denominator is zero (returning zero if
        // so) and if non-zero, returns the value of the division.

        let nom  = cell(name_of_str("nom"), 0 as usize);
        let den  = cell(name_of_str("den"), 1 as usize);

        // In Rust, cloning is explicit:
        let den2 = den.clone(); // here, we clone the _global reference_ to the cell.
        let den3 = den.clone(); // here, we clone the _global reference_ to the cell, again.

        let div  = thunk![ name_of_str("div") =>> get!(nom) / get!(den) ];
        let root = thunk![ name_of_str("t")   =>> if get!(den2) == 0 { 0 } else { get!(div) } ];

        assert_eq!(get!(root), 0);
        set(&den3, 0);
        assert_eq!(get!(root), 0);
    }

    /// Compare to this sound behavior to the unsound behavior from
    /// JaneStreet 'Incremental' libary.  In particular, Yit's gist
    /// shows the problematic change propagation behavior:
    /// https://gist.github.com/khooyp/98abc0e64dc296deaa48
    #[test]
    fn test1_short_macros () {

        use std::rc::Rc;
        use adapton::macros::*;
        use adapton::engine::*;
        manage::init_dcg();

        // Construct two mutable inputs, `nom` and `den`, a
        // computation `div` that divides the nominator in `nom` by
        // the denominator in `den`, and a root thunk `t` that first
        // checks whether the denominator is zero (returning zero if
        // so) and if non-zero, returns the value of the division.

        let nom  = cell!(0);
        let den  = cell!(1);

        // In Rust, cloning is explicit:
        let den2 = den.clone(); // here, we clone the _global reference_ to the cell.
        let den3 = den.clone(); // here, we clone the _global reference_ to the cell, again.

        let div  = thunk![ get!(nom) / get!(den) ];
        let root = thunk![ if get!(den2) == 0 { 0 } else { get!(div) } ];

        assert_eq!(get!(root), 0);
        set(&den3, 0);
        assert_eq!(get!(root), 0);
    }
}

mod engine_is_demand_driven {

    #[test]
    fn test1() {
        // TODO
    }

}

mod engine_api {
    //! This module tests gives unit tests for the engine's core API

    #[test]
    fn force_cell () {
        use adapton::engine::*;
        manage::init_dcg();
        let a : u32      = 1234;
        let b : Art<u32> = cell(name_of_usize(0), a);
        let c : u32      = force(&b);
        assert_eq!(a, c);
    }

    #[test]
    fn force_map_cell () {
        use adapton::engine::*;
        manage::init_dcg();
        let a : u32      = 1234;
        let b : Art<u32> = cell(name_of_usize(0), a);
        let c : u64      = force_map(&b, |_,x| x as u64);
        assert_eq!(a as u64, c);
    }

    #[test]
    fn force_map_cell_project () {
        use adapton::engine::*;
        manage::init_dcg();
        let pair = (1234 as usize, 5678 as usize);
        let c    = cell(name_of_usize(0), pair);
        let fst  = force_map(&c, |_,x| x.0);
        let snd  = force_map(&c, |_,x| x.1);
        assert_eq!(pair.0, fst);
        assert_eq!(pair.1, snd);
    }

    #[test]
    fn force_map_prunes_dirty_traversal () {
        // Test whether using force_map correctly prunes dirtying;
        // this test traces the engine, counts the number of dirtying
        // steps, and ensures that this count is zero, as expected.
        use std::rc::Rc;
        use adapton::macros::*;
        use adapton::engine::*;
        manage::init_dcg();
        reflect::dcg_reflect_begin();
        let pair = (1234 as usize, 5678 as usize);
        let c    = cell(name_of_usize(0), pair);
        let t = thunk![ name_of_usize(1) =>> {
            let fst = force_map(&c, |_,x| x.0);
            fst + 100
        }];
        assert_eq!(force(&t), 1334);
        let pair = (1234 as usize, 8765 as usize);
        let _    = cell(name_of_usize(0), pair);
        assert_eq!(force(&t), 1334);
        let traces = reflect::dcg_reflect_end();
        let counts = reflect::trace::trace_count(&traces, Some(1));
        assert_eq!(counts.dirty.0, 0);
        assert_eq!(counts.dirty.1, 0);
    }

    #[test]
    fn force_map_thunk () {
        use std::rc::Rc;
        use adapton::macros::*;
        use adapton::engine::*;
        manage::init_dcg();
        let a : u32      = 1234;
        let b : Art<u32> = thunk![ name_of_usize(0) =>> a];
        let c : u64      = force_map(&b, |_,x| x as u64);
        assert_eq!(a as u64, c);
    }
}
<commit_msg>engine change propagation test: avoid expensive subcomputation, via switching<commit_after>#[macro_use]
extern crate adapton;

mod engine_is_from_scratch_consistent {
    //! This module tests that change propagation is from-scratch consistent

    /// Compare to this sound behavior to the unsound behavior from
    /// JaneStreet 'Incremental' libary.  In particular, Yit's gist
    /// shows the problematic change propagation behavior for a
    /// similar example program (dividing by zero when it should not):
    /// https://gist.github.com/khooyp/98abc0e64dc296deaa48
    #[test]
    fn avoid_divide_by_zero () {

        use std::rc::Rc;
        use adapton::macros::*;
        use adapton::engine::*;
        manage::init_dcg();

        // Construct two mutable inputs, `nom` and `den`, a
        // computation `div` that divides the nominator in `nom` by
        // the denominator in `den`, and a root thunk `t` that first
        // checks whether the denominator is zero (returning zero if
        // so) and if non-zero, returns the value of the division.

        let nom  = cell!(0);
        let den  = cell!(1);

        // In Rust, cloning is explicit:
        let den2 = den.clone(); // here, we clone the _global reference_ to the cell.
        let den3 = den.clone(); // here, we clone the _global reference_ to the cell, again.

        let div  = thunk![ get!(nom) / get!(den) ];
        let root = thunk![ if get!(den2) == 0 { 0 } else { get!(div) } ];

        assert_eq!(get!(root), 0);
        set(&den3, 0);
        assert_eq!(get!(root), 0);
    }

    #[test]
    fn avoid_expensive_subcomp () {

        use std::rc::Rc;
        use adapton::macros::*;
        use adapton::engine::*;
        use std::hash::{Hash, SipHasher, Hasher};

        manage::init_dcg();

        let flag = cell!(true); // flag: whether or not to do "iterative hash"
        let iter = cell!(3);    // iter: iterations for hashing
        let inp  = cell!(42);   // inp1: input value to hash

        let inp1  = inp.clone();  // we use inp non-linearly below
        let inp2  = inp.clone();  // we use inp non-linearly below
        let flag1 = flag.clone(); // we use flag non-linearly below
        let iter1 = iter.clone(); // we use iter non-linearly below

        let iter_hash = thunk![{
            let inp_val = get!(inp); // value to hash iteratively
            let mut hash_state = SipHasher::new();
            for _ in 0..get!(iter) { // hash iteratively, `iter` number of times
                inp_val.hash(&mut hash_state);
            };
            assert!(get!(iter) < 100); // For Testing: Too many iters is an error!
            hash_state.finish() // returns final hash value
        }];
        let root = thunk![ // switches between hashing iteratively, or not
            if get!(flag) { get!(iter_hash) }
            else { get!(inp1) }
        ];

        assert!(get!(root) != get!(inp2));
        set(&flag1, false);
        set(&iter1, 999999999);
        assert!(get!(root) == get!(inp2));
    }
}

mod engine_is_demand_driven {

    #[test]
    fn test1() {
        // TODO
    }

}

mod engine_api {
    //! This module tests gives unit tests for the engine's core API

    #[test]
    fn force_cell () {
        use adapton::engine::*;
        manage::init_dcg();
        let a : u32      = 1234;
        let b : Art<u32> = cell(name_of_usize(0), a);
        let c : u32      = force(&b);
        assert_eq!(a, c);
    }

    #[test]
    fn force_map_cell () {
        use adapton::engine::*;
        manage::init_dcg();
        let a : u32      = 1234;
        let b : Art<u32> = cell(name_of_usize(0), a);
        let c : u64      = force_map(&b, |_,x| x as u64);
        assert_eq!(a as u64, c);
    }

    #[test]
    fn force_map_cell_project () {
        use adapton::engine::*;
        manage::init_dcg();
        let pair = (1234 as usize, 5678 as usize);
        let c    = cell(name_of_usize(0), pair);
        let fst  = force_map(&c, |_,x| x.0);
        let snd  = force_map(&c, |_,x| x.1);
        assert_eq!(pair.0, fst);
        assert_eq!(pair.1, snd);
    }

    #[test]
    fn force_map_prunes_dirty_traversal () {
        // Test whether using force_map correctly prunes dirtying;
        // this test traces the engine, counts the number of dirtying
        // steps, and ensures that this count is zero, as expected.
        use std::rc::Rc;
        use adapton::macros::*;
        use adapton::engine::*;
        manage::init_dcg();
        reflect::dcg_reflect_begin();
        let pair = (1234 as usize, 5678 as usize);
        let c    = cell(name_of_usize(0), pair);
        let t = thunk![ name_of_usize(1) =>> {
            let fst = force_map(&c, |_,x| x.0);
            fst + 100
        }];
        assert_eq!(force(&t), 1334);
        let pair = (1234 as usize, 8765 as usize);
        let _    = cell(name_of_usize(0), pair);
        assert_eq!(force(&t), 1334);
        let traces = reflect::dcg_reflect_end();
        let counts = reflect::trace::trace_count(&traces, Some(1));
        assert_eq!(counts.dirty.0, 0);
        assert_eq!(counts.dirty.1, 0);
    }

    #[test]
    fn force_map_thunk () {
        use std::rc::Rc;
        use adapton::macros::*;
        use adapton::engine::*;
        manage::init_dcg();
        let a : u32      = 1234;
        let b : Art<u32> = thunk![ name_of_usize(0) =>> a];
        let c : u64      = force_map(&b, |_,x| x as u64);
        assert_eq!(a as u64, c);
    }
}
<|endoftext|>


<commit_before>//! Trace exporters
use crate::Resource;
use futures_util::future::BoxFuture;
use opentelemetry_api::trace::{Event, Link, SpanContext, SpanId, SpanKind, Status, TraceError};
use std::borrow::Cow;
use std::fmt::Debug;
use std::time::SystemTime;

pub mod stdout;

/// Describes the result of an export.
pub type ExportResult = Result<(), TraceError>;

/// `SpanExporter` defines the interface that protocol-specific exporters must
/// implement so that they can be plugged into OpenTelemetry SDK and support
/// sending of telemetry data.
///
/// The goal of the interface is to minimize burden of implementation for
/// protocol-dependent telemetry exporters. The protocol exporter is expected to
/// be primarily a simple telemetry data encoder and transmitter.
pub trait SpanExporter: Send + Debug {
    /// Exports a batch of readable spans. Protocol exporters that will
    /// implement this function are typically expected to serialize and transmit
    /// the data to the destination.
    ///
    /// This function will never be called concurrently for the same exporter
    /// instance. It can be called again only after the current call returns.
    ///
    /// This function must not block indefinitely, there must be a reasonable
    /// upper limit after which the call must time out with an error result.
    ///
    /// Any retry logic that is required by the exporter is the responsibility
    /// of the exporter.
    fn export(&mut self, batch: Vec<SpanData>) -> BoxFuture<'static, ExportResult>;

    /// Shuts down the exporter. Called when SDK is shut down. This is an
    /// opportunity for exporter to do any cleanup required.
    ///
    /// This function should be called only once for each `SpanExporter`
    /// instance. After the call to `shutdown`, subsequent calls to `export` are
    /// not allowed and should return an error.
    ///
    /// This function should not block indefinitely (e.g. if it attempts to
    /// flush the data and the destination is unavailable). SDK authors
    /// can decide if they want to make the shutdown timeout
    /// configurable.
    fn shutdown(&mut self) {}
}

/// `SpanData` contains all the information collected by a `Span` and can be used
/// by exporters as a standard input.
#[derive(Clone, Debug, PartialEq)]
pub struct SpanData {
    /// Exportable `SpanContext`
    pub span_context: SpanContext,
    /// Span parent id
    pub parent_span_id: SpanId,
    /// Span kind
    pub span_kind: SpanKind,
    /// Span name
    pub name: Cow<'static, str>,
    /// Span start time
    pub start_time: SystemTime,
    /// Span end time
    pub end_time: SystemTime,
    /// Span attributes
    pub attributes: crate::trace::EvictedHashMap,
    /// Span events
    pub events: crate::trace::EvictedQueue<Event>,
    /// Span Links
    pub links: crate::trace::EvictedQueue<Link>,
    /// Span status
    pub status: Status,
    /// Resource contains attributes representing an entity that produced this span.
    pub resource: Cow<'static, Resource>,
    /// Instrumentation library that produced this span
    pub instrumentation_lib: crate::InstrumentationLibrary,
}
<commit_msg>Add `SpanExporter::ForceFlush` and default implementation (#845)<commit_after>//! Trace exporters
use crate::Resource;
use futures_util::future::BoxFuture;
use opentelemetry_api::trace::{Event, Link, SpanContext, SpanId, SpanKind, Status, TraceError};
use std::borrow::Cow;
use std::fmt::Debug;
use std::time::SystemTime;

pub mod stdout;

/// Describes the result of an export.
pub type ExportResult = Result<(), TraceError>;

/// `SpanExporter` defines the interface that protocol-specific exporters must
/// implement so that they can be plugged into OpenTelemetry SDK and support
/// sending of telemetry data.
///
/// The goal of the interface is to minimize burden of implementation for
/// protocol-dependent telemetry exporters. The protocol exporter is expected to
/// be primarily a simple telemetry data encoder and transmitter.
pub trait SpanExporter: Send + Debug {
    /// Exports a batch of readable spans. Protocol exporters that will
    /// implement this function are typically expected to serialize and transmit
    /// the data to the destination.
    ///
    /// This function will never be called concurrently for the same exporter
    /// instance. It can be called again only after the current call returns.
    ///
    /// This function must not block indefinitely, there must be a reasonable
    /// upper limit after which the call must time out with an error result.
    ///
    /// Any retry logic that is required by the exporter is the responsibility
    /// of the exporter.
    fn export(&mut self, batch: Vec<SpanData>) -> BoxFuture<'static, ExportResult>;

    /// Shuts down the exporter. Called when SDK is shut down. This is an
    /// opportunity for exporter to do any cleanup required.
    ///
    /// This function should be called only once for each `SpanExporter`
    /// instance. After the call to `shutdown`, subsequent calls to `export` are
    /// not allowed and should return an error.
    ///
    /// This function should not block indefinitely (e.g. if it attempts to
    /// flush the data and the destination is unavailable). SDK authors
    /// can decide if they want to make the shutdown timeout
    /// configurable.
    fn shutdown(&mut self) {}

    /// This is a hint to ensure that the export of any Spans the exporter
    /// has received prior to the call to this function SHOULD be completed
    /// as soon as possible, preferably before returning from this method.
    ///
    /// This function SHOULD provide a way to let the caller know
    /// whether it succeeded, failed or timed out.
    ///
    /// This function SHOULD only be called in cases where it is absolutely necessary,
    /// such as when using some FaaS providers that may suspend the process after
    /// an invocation, but before the exporter exports the completed spans.
    ///
    /// This function SHOULD complete or abort within some timeout. This function can be
    /// implemented as a blocking API or an asynchronous API which notifies the caller via
    /// a callback or an event. OpenTelemetry client authors can decide if they want to
    /// make the flush timeout configurable.
    fn force_flush(&mut self) -> BoxFuture<'static, ExportResult> {
        Box::pin(async { Ok(()) })
    }
}

/// `SpanData` contains all the information collected by a `Span` and can be used
/// by exporters as a standard input.
#[derive(Clone, Debug, PartialEq)]
pub struct SpanData {
    /// Exportable `SpanContext`
    pub span_context: SpanContext,
    /// Span parent id
    pub parent_span_id: SpanId,
    /// Span kind
    pub span_kind: SpanKind,
    /// Span name
    pub name: Cow<'static, str>,
    /// Span start time
    pub start_time: SystemTime,
    /// Span end time
    pub end_time: SystemTime,
    /// Span attributes
    pub attributes: crate::trace::EvictedHashMap,
    /// Span events
    pub events: crate::trace::EvictedQueue<Event>,
    /// Span Links
    pub links: crate::trace::EvictedQueue<Link>,
    /// Span status
    pub status: Status,
    /// Resource contains attributes representing an entity that produced this span.
    pub resource: Cow<'static, Resource>,
    /// Instrumentation library that produced this span
    pub instrumentation_lib: crate::InstrumentationLibrary,
}
<|endoftext|>


<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(mut index), ProgramStatus::Seeking(_)) => {
                let (new_index, new_depth, new_status) = self.handle_jump_forward(vm, index);
                self.instruction_pointer = Some(new_index);
                self.current_depth = new_depth;
                self.status = new_status;
                if new_index < self.instructions.len() { self.execute(vm); }
            }

            (Some(mut index), ProgramStatus::Normal) => {
                while index < self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpBackward => self.handle_jump_backward(vm, &mut index),

                        Command::JumpForward => {
                            let (new_index, new_depth, new_status) = self.handle_jump_forward(vm, index);
                            index = new_index;
                            self.current_depth = new_depth;
                            self.status = new_status;
                        }

                        command => {
                            vm.apply(command);
                            index += 1;
                        }
                    }
                }

                self.instruction_pointer = Some(index);
            }

            _ => {}
        }
    }

    fn handle_jump_backward(&mut self, vm: &VM, index_ref: &mut usize) {
        match vm.cells[vm.data_pointer] {
            0 => {
                self.current_depth -= 1;
                *index_ref += 1;
            }

            _ => {
                let goal_depth = self.current_depth;
                for index in (0..*index_ref).rev() {
                    match self.instructions[index] {
                        Command::JumpBackward => self.current_depth += 1,
                        Command::JumpForward => {
                            if self.current_depth == goal_depth {
                                *index_ref = index + 1;
                                return;
                            }
                            self.current_depth -= 1;
                        }
                        _ => {}
                    }
                }
                panic!("No starting brace found!");
            }
        }
    }

    fn seek_forward(&self, starting_index: usize) -> (usize, u64, ProgramStatus) {
        match self.status {
            ProgramStatus::Seeking(goal_depth) => {
                let mut depth = self.current_depth;
                for index in starting_index..self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpForward => depth += 1,
                        Command::JumpBackward => depth  -= 1,
                        _ => {}
                    }
                    if depth == goal_depth {
                        return (index + 1, self.current_depth, ProgramStatus::Normal);
                    }
                }

                return (self.instructions.len()
                       , self.current_depth
                       , ProgramStatus::Seeking(goal_depth));
            }

            ProgramStatus::Normal => return (starting_index, self.current_depth, self.status)
        }
    }

    fn handle_jump_forward(&self, vm: &VM, index: usize) -> (usize, u64, ProgramStatus){
        match (vm.cells[vm.data_pointer], self.status) {
            (0, ProgramStatus::Normal) => return self.seek_forward(index),
            (_, ProgramStatus::Normal) => return (index + 1, self.current_depth + 1, ProgramStatus::Normal),
            (_, ProgramStatus::Seeking(_)) => self.seek_forward(index),

        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    pub fn test_seek_forward_normal() {
        let mut program = Program {
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Seeking(0),
            instructions: vec![
                Command::JumpForward,
                Command::JumpForward,
                Command::JumpBackward,
                Command::JumpBackward,
            ],
        };
        let mut index = 0;
        program.seek_forward(&mut index);
        assert_eq!(index, 4);
        assert_eq!(program.status, ProgramStatus::Normal);
    }

    #[test]
    pub fn test_seek_forward_seeking() {
        let mut program = Program {
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Seeking(0),
            instructions: vec![
                Command::JumpForward,
                Command::JumpForward,
                Command::JumpBackward,
            ],
        };
        let mut index = 0;
        program.seek_forward(&mut index);
        assert_eq!(index, 3);
        assert_eq!(program.status, ProgramStatus::Seeking(0));
    }
}
<commit_msg>Update unit tests for seek_forward<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(mut index), ProgramStatus::Seeking(_)) => {
                let (new_index, new_depth, new_status) = self.handle_jump_forward(vm, index);
                self.instruction_pointer = Some(new_index);
                self.current_depth = new_depth;
                self.status = new_status;
                if new_index < self.instructions.len() { self.execute(vm); }
            }

            (Some(mut index), ProgramStatus::Normal) => {
                while index < self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpBackward => self.handle_jump_backward(vm, &mut index),

                        Command::JumpForward => {
                            let (new_index, new_depth, new_status) = self.handle_jump_forward(vm, index);
                            index = new_index;
                            self.current_depth = new_depth;
                            self.status = new_status;
                        }

                        command => {
                            vm.apply(command);
                            index += 1;
                        }
                    }
                }

                self.instruction_pointer = Some(index);
            }

            _ => {}
        }
    }

    fn handle_jump_backward(&mut self, vm: &VM, index_ref: &mut usize) {
        match vm.cells[vm.data_pointer] {
            0 => {
                self.current_depth -= 1;
                *index_ref += 1;
            }

            _ => {
                let goal_depth = self.current_depth;
                for index in (0..*index_ref).rev() {
                    match self.instructions[index] {
                        Command::JumpBackward => self.current_depth += 1,
                        Command::JumpForward => {
                            if self.current_depth == goal_depth {
                                *index_ref = index + 1;
                                return;
                            }
                            self.current_depth -= 1;
                        }
                        _ => {}
                    }
                }
                panic!("No starting brace found!");
            }
        }
    }

    fn seek_forward(&self, starting_index: usize) -> (usize, u64, ProgramStatus) {
        match self.status {
            ProgramStatus::Seeking(goal_depth) => {
                let mut depth = self.current_depth;
                for index in starting_index..self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpForward => depth += 1,
                        Command::JumpBackward => depth  -= 1,
                        _ => {}
                    }
                    if depth == goal_depth {
                        return (index + 1, self.current_depth, ProgramStatus::Normal);
                    }
                }

                return (self.instructions.len()
                       , self.current_depth
                       , ProgramStatus::Seeking(goal_depth));
            }

            ProgramStatus::Normal => return (starting_index, self.current_depth, self.status)
        }
    }

    fn handle_jump_forward(&self, vm: &VM, index: usize) -> (usize, u64, ProgramStatus){
        match (vm.cells[vm.data_pointer], self.status) {
            (0, ProgramStatus::Normal) => return self.seek_forward(index),
            (_, ProgramStatus::Normal) => return (index + 1, self.current_depth + 1, ProgramStatus::Normal),
            (_, ProgramStatus::Seeking(_)) => self.seek_forward(index),

        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    pub fn test_seek_forward_normal() {
        let mut program = Program {
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Seeking(0),
            instructions: vec![
                Command::JumpForward,
                Command::JumpForward,
                Command::JumpBackward,
                Command::JumpBackward,
            ],
        };
        let mut index = 0;
        let (new_index, new_depth, new_status) = program.seek_forward(index);
        assert_eq!(new_depth, 0);
        assert_eq!(new_index, 4);
        assert_eq!(new_status, ProgramStatus::Normal);
    }

    #[test]
    pub fn test_seek_forward_seeking() {
        let mut program = Program {
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Seeking(0),
            instructions: vec![
                Command::JumpForward,
                Command::JumpForward,
                Command::JumpBackward,
            ],
        };
        let mut index = 0;
        let (new_index, new_depth, new_status) = program.seek_forward(index);
        assert_eq!(new_depth, 1);
        assert_eq!(new_index, 3);
        assert_eq!(new_status, ProgramStatus::Seeking(0));
    }
}
<|endoftext|>


<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(index), ProgramStatus::Seeking(goal)) if index < self.instructions.len() => {}

            (Some(index), ProgramStatus::Normal) if index < self.instructions.len() => {}

            _ => {}
        }
    }
}
<commit_msg>Add find_by utility function<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions: Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

fn find_by<T, F>(list: &[T], predicate: F, start: Option<usize>) -> Option<usize> where F: Fn(&T) -> bool {
    let start = start.unwrap_or(0);
    for (offset, element) in list.iter().enumerate() {
        if predicate(element) { return Some(start + offset); }
    }

    return None;
}

impl Program {
    pub fn new() -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() {
            self.instruction_pointer = Some(0);
        }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(index), ProgramStatus::Seeking(goal)) if index < self.instructions.len() => {}

            (Some(index), ProgramStatus::Normal) if index < self.instructions.len() => {}

            _ => {}
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate failure;

#[macro_use]
extern crate crate_compile_test;

use crate_compile_test::prelude::*;
use std::env::{current_dir, current_exe};
use std::path::Path;

mod steps;
use steps::{
    assembly::StepFactory as AssemblyTestStepFactory, ir::StepFactory as IRTestStepFactory,
    verification::StepFactory as VerificationTestStepFactory,
};

fn ptx_assembly_tests(tester: &mut TestRunner) {
    tester.add("Debug PTX Assembly", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Debug);

        config
            .additional_steps
            .push(Box::new(AssemblyTestStepFactory::new()));

        config
    });

    tester.add("Release PTX Assembly", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Release);

        config
            .additional_steps
            .push(Box::new(AssemblyTestStepFactory::new()));

        config
    });

    tester.add("Debug PTX Assembly Verification", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Debug);

        config.crates_filter = Box::new(|path| {
            VerificationTestStepFactory::is_runnable()
                && path != Path::new("examples/undefined-ref")
        });

        config
            .additional_steps
            .push(Box::new(VerificationTestStepFactory::new()));

        config
    });

    tester.add("Release PTX Assembly Verification", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Release);

        config.crates_filter = Box::new(|path| {
            VerificationTestStepFactory::is_runnable()
                && path != Path::new("examples/undefined-ref")
        });

        config
            .additional_steps
            .push(Box::new(VerificationTestStepFactory::new()));

        config
    });
}

fn ir_tests(tester: &mut TestRunner) {
    tester.add("Debug IR", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Debug);

        config
            .additional_steps
            .push(Box::new(IRTestStepFactory::new()));

        config
    });

    tester.add("Release IR", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Release);

        config
            .additional_steps
            .push(Box::new(IRTestStepFactory::new()));

        config
    });
}

fn failure_tests(tester: &mut TestRunner) {
    tester.add("Debug linking fail", || {
        create_config(Mode::BuildFail, Profile::Debug)
    });

    tester.add("Release linking fail", || {
        create_config(Mode::BuildFail, Profile::Release)
    });
}

bootstrap_compilation_tests![ptx_assembly_tests, ir_tests, failure_tests];

fn create_config(mode: Mode, profile: Profile) -> Config {
    let mut config = Config::new(mode, "examples");

    config.cargo_command = "xargo".into();
    config.profile = profile;
    config.target = Some("nvptx64-nvidia-cuda".into());

    match config.mode {
        Mode::BuildFail => {
            config.crates_filter = Box::new(|path| path == Path::new("examples/undefined-ref"));
        }

        Mode::BuildSuccess => {
            config.crates_filter = Box::new(|path| path != Path::new("examples/undefined-ref"));
        }

        _ => unimplemented!(),
    };

    config.add_cargo_env(
        "CARGO_TARGET_NVPTX64_NVIDIA_CUDA_LINKER",
        &current_exe()
            .unwrap()
            .parent()
            .unwrap()
            .parent()
            .unwrap()
            .join("legacy-ptx-linker")
            .to_string_lossy(),
    );

    config.add_cargo_env(
        "RUST_TARGET_PATH",
        &current_dir().unwrap().join("targets").to_string_lossy(),
    );

    config
}
<commit_msg>Emit IR during tests<commit_after>#[macro_use]
extern crate failure;

#[macro_use]
extern crate crate_compile_test;

use crate_compile_test::prelude::*;
use std::env::{current_dir, current_exe};
use std::path::Path;

mod steps;
use steps::{
    assembly::StepFactory as AssemblyTestStepFactory, ir::StepFactory as IRTestStepFactory,
    verification::StepFactory as VerificationTestStepFactory,
};

fn ptx_assembly_tests(tester: &mut TestRunner) {
    tester.add("Debug PTX Assembly", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Debug);

        config
            .additional_steps
            .push(Box::new(AssemblyTestStepFactory::new()));

        config
    });

    tester.add("Release PTX Assembly", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Release);

        config
            .additional_steps
            .push(Box::new(AssemblyTestStepFactory::new()));

        config
    });

    tester.add("Debug PTX Assembly Verification", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Debug);

        config.crates_filter = Box::new(|path| {
            VerificationTestStepFactory::is_runnable()
                && path != Path::new("examples/undefined-ref")
        });

        config
            .additional_steps
            .push(Box::new(VerificationTestStepFactory::new()));

        config
    });

    tester.add("Release PTX Assembly Verification", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Release);

        config.crates_filter = Box::new(|path| {
            VerificationTestStepFactory::is_runnable()
                && path != Path::new("examples/undefined-ref")
        });

        config
            .additional_steps
            .push(Box::new(VerificationTestStepFactory::new()));

        config
    });
}

fn ir_tests(tester: &mut TestRunner) {
    tester.add("Debug IR", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Debug);

        config
            .additional_steps
            .push(Box::new(IRTestStepFactory::new()));

        config
    });

    tester.add("Release IR", || {
        let mut config = create_config(Mode::BuildSuccess, Profile::Release);

        config
            .additional_steps
            .push(Box::new(IRTestStepFactory::new()));

        config
    });
}

fn failure_tests(tester: &mut TestRunner) {
    tester.add("Debug linking fail", || {
        create_config(Mode::BuildFail, Profile::Debug)
    });

    tester.add("Release linking fail", || {
        create_config(Mode::BuildFail, Profile::Release)
    });
}

bootstrap_compilation_tests![ptx_assembly_tests, ir_tests, failure_tests];

fn create_config(mode: Mode, profile: Profile) -> Config {
    let mut config = Config::new(mode, "examples");

    config.cargo_command = "xargo".into();
    config.profile = profile;
    config.target = Some("nvptx64-nvidia-cuda".into());

    match config.mode {
        Mode::BuildFail => {
            config.crates_filter = Box::new(|path| path == Path::new("examples/undefined-ref"));
        }

        Mode::BuildSuccess => {
            config.crates_filter = Box::new(|path| path != Path::new("examples/undefined-ref"));
        }

        _ => unimplemented!(),
    };

    config.add_cargo_env(
        "CARGO_TARGET_NVPTX64_NVIDIA_CUDA_LINKER",
        &current_exe()
            .unwrap()
            .parent()
            .unwrap()
            .parent()
            .unwrap()
            .join("legacy-ptx-linker")
            .to_string_lossy(),
    );

    config.add_cargo_env("RUSTFLAGS", "-Clink-arg=--emit=asm,llvm-ir");
    config.add_cargo_env(
        "RUST_TARGET_PATH",
        &current_dir().unwrap().join("targets").to_string_lossy(),
    );

    config
}
<|endoftext|>


<commit_before>#![crate_name = "timeout"]
#![feature(collections, core, io, old_io, rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::old_io::{PathDoesntExist, FileNotFound};
use std::old_io::process::{Command, ExitStatus, ExitSignal, InheritFd};

#[path = "../common/util.rs"]
#[macro_use]
mod util;

#[path = "../common/time.rs"]
mod time;

#[path = "../common/signals.rs"]
mod signals;

extern {
    pub fn setpgid(_: libc::pid_t, _: libc::pid_t) -> libc::c_int;
}

static NAME: &'static str = "timeout";
static VERSION: &'static str = "1.0.0";

static ERR_EXIT_STATUS: i32 = 125;

pub fn uumain(args: Vec<String>) -> i32 {
    let program = args[0].clone();

    let opts = [
        getopts::optflag("", "preserve-status", "exit with the same status as COMMAND, even when the command times out"),
        getopts::optflag("", "foreground", "when not running timeout directly from a shell prompt, allow COMMAND to read from the TTY and get TTY signals; in this mode, children of COMMAND will not be timed out"),
        getopts::optopt("k", "kill-after", "also send a KILL signal if COMMAND is still running this long after the initial signal was sent", "DURATION"),
        getopts::optflag("s", "signal", "specify the signal to be sent on timeout; SIGNAL may be a name like 'HUP' or a number; see 'kill -l' for a list of signals"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit")
    ];
    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(ERR_EXIT_STATUS, "{}", f)
        }
    };
    if matches.opt_present("help") {
        print!("{} {}

Usage:
  {} [OPTION] DURATION COMMAND [ARG]...

{}", NAME, VERSION, program, getopts::usage("Start COMMAND, and kill it if still running after DURATION.", &opts));
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else if matches.free.len() < 2 {
        show_error!("missing an argument");
        show_error!("for help, try '{0} --help'", program);
        return ERR_EXIT_STATUS;
    } else {
        let status = matches.opt_present("preserve-status");
        let foreground = matches.opt_present("foreground");
        let kill_after = match matches.opt_str("kill-after") {
            Some(tstr) => match time::from_str(tstr.as_slice()) {
                Ok(time) => time,
                Err(f) => {
                    show_error!("{}", f);
                    return ERR_EXIT_STATUS;
                }
            },
            None => 0f64
        };
        let signal = match matches.opt_str("signal") {
            Some(sigstr) => match signals::signal_by_name_or_value(sigstr.as_slice()) {
                Some(sig) => sig,
                None => {
                    show_error!("invalid signal '{}'", sigstr);
                    return ERR_EXIT_STATUS;
                }
            },
            None => signals::signal_by_name_or_value("TERM").unwrap()
        };
        let duration = match time::from_str(matches.free[0].as_slice()) {
            Ok(time) => time,
            Err(f) => {
                show_error!("{}", f);
                return ERR_EXIT_STATUS;
            }
        };
        return timeout(matches.free[1].as_slice(), &matches.free[2..], duration, signal, kill_after, foreground, status);
    }

    0
}

fn timeout(cmdname: &str, args: &[String], duration: f64, signal: usize, kill_after: f64, foreground: bool, preserve_status: bool) -> i32 {
    if !foreground {
        unsafe { setpgid(0, 0) };
    }
    let mut process = match Command::new(cmdname).args(args)
                                                 .stdin(InheritFd(0))
                                                 .stdout(InheritFd(1))
                                                 .stderr(InheritFd(2))
                                                 .spawn() {
        Ok(p) => p,
        Err(err) => {
            show_error!("failed to execute process: {}", err);
            if err.kind == FileNotFound || err.kind == PathDoesntExist {
                // XXX: not sure which to use
                return 127;
            } else {
                // XXX: this may not be 100% correct...
                return 126;
            }
        }
    };
    process.set_timeout(Some((duration * 1000f64) as u64));  // FIXME: this ignores the f64...
    match process.wait() {
        Ok(status) => match status {
            ExitStatus(stat) => stat as i32,
            ExitSignal(stat) => stat as i32
        },
        Err(_) => {
            return_if_err!(ERR_EXIT_STATUS, process.signal(signal as isize));
            process.set_timeout(Some((kill_after * 1000f64) as u64));
            match process.wait() {
                Ok(status) => {
                    if preserve_status {
                        match status {
                            ExitStatus(stat) => stat as i32,
                            ExitSignal(stat) => stat as i32
                        }
                    } else {
                        124
                    }
                }
                Err(_) => {
                    if kill_after == 0f64 {
                        // XXX: this may not be right
                        return 124;
                    }
                    return_if_err!(ERR_EXIT_STATUS, process.signal(signals::signal_by_name_or_value("KILL").unwrap() as isize));
                    process.set_timeout(None);
                    return_if_err!(ERR_EXIT_STATUS, process.wait());
                    137
                }
            }
        }
    }
}
<commit_msg>Update timeout.rs to new io<commit_after>#![crate_name = "timeout"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Arcterus <arcterus@mail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::io::{ErrorKind, Write};
use std::process::{Command, Stdio};
use std::os::unix::process::ExitStatusExt;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

#[path = "../common/time.rs"]
mod time;

#[path = "../common/signals.rs"]
mod signals;

extern {
    pub fn setpgid(_: libc::pid_t, _: libc::pid_t) -> libc::c_int;
}

static NAME: &'static str = "timeout";
static VERSION: &'static str = "1.0.0";

static ERR_EXIT_STATUS: i32 = 125;

pub fn uumain(args: Vec<String>) -> i32 {
    let program = args[0].clone();

    let mut opts = getopts::Options::new();
    opts.optflag("", "preserve-status", "exit with the same status as COMMAND, even when the command times out");
    opts.optflag("", "foreground", "when not running timeout directly from a shell prompt, allow COMMAND to read from the TTY and get TTY signals; in this mode, children of COMMAND will not be timed out");
    opts.optopt("k", "kill-after", "also send a KILL signal if COMMAND is still running this long after the initial signal was sent", "DURATION");
    opts.optflag("s", "signal", "specify the signal to be sent on timeout; SIGNAL may be a name like 'HUP' or a number; see 'kill -l' for a list of signals");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            crash!(ERR_EXIT_STATUS, "{}", f)
        }
    };
    if matches.opt_present("help") {
        print!("{} {}

Usage:
  {} [OPTION] DURATION COMMAND [ARG]...

{}", NAME, VERSION, program, &opts.usage("Start COMMAND, and kill it if still running after DURATION."));
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else if matches.free.len() < 2 {
        show_error!("missing an argument");
        show_error!("for help, try '{0} --help'", program);
        return ERR_EXIT_STATUS;
    } else {
        let status = matches.opt_present("preserve-status");
        let foreground = matches.opt_present("foreground");
        let kill_after = match matches.opt_str("kill-after") {
            Some(tstr) => match time::from_str(&tstr) {
                Ok(time) => time,
                Err(f) => {
                    show_error!("{}", f);
                    return ERR_EXIT_STATUS;
                }
            },
            None => 0f64
        };
        let signal = match matches.opt_str("signal") {
            Some(sigstr) => match signals::signal_by_name_or_value(&sigstr) {
                Some(sig) => sig,
                None => {
                    show_error!("invalid signal '{}'", sigstr);
                    return ERR_EXIT_STATUS;
                }
            },
            None => signals::signal_by_name_or_value("TERM").unwrap()
        };
        let duration = match time::from_str(&matches.free[0]) {
            Ok(time) => time,
            Err(f) => {
                show_error!("{}", f);
                return ERR_EXIT_STATUS;
            }
        };
        return timeout(&matches.free[1], &matches.free[2..], duration, signal, kill_after, foreground, status);
    }

    0
}

fn timeout(cmdname: &str, args: &[String], duration: f64, signal: usize, kill_after: f64, foreground: bool, preserve_status: bool) -> i32 {
    if !foreground {
        unsafe { setpgid(0, 0) };
    }
    let mut process = match Command::new(cmdname).args(args)
                                                 .stdin(Stdio::inherit())
                                                 .stdout(Stdio::inherit())
                                                 .stderr(Stdio::inherit())
                                                 .spawn() {
        Ok(p) => p,
        Err(err) => {
            show_error!("failed to execute process: {}", err);
            if err.kind() == ErrorKind::NotFound {
                // XXX: not sure which to use
                return 127;
            } else {
                // XXX: this may not be 100% correct...
                return 126;
            }
        }
    };
    process.set_timeout(Some((duration * 1000f64) as u64));  // FIXME: this ignores the f64...
    match process.wait() {
        Ok(status) => status.code().unwrap_or_else(|| status.signal().unwrap()),
        Err(_) => {
            return_if_err!(ERR_EXIT_STATUS, process.signal(signal as isize));
            process.set_timeout(Some((kill_after * 1000f64) as u64));
            match process.wait() {
                Ok(status) => {
                    if preserve_status {
                        status.code().unwrap_or_else(|| status.signal().unwrap())
                    } else {
                        124
                    }
                }
                Err(_) => {
                    if kill_after == 0f64 {
                        // XXX: this may not be right
                        return 124;
                    }
                    return_if_err!(ERR_EXIT_STATUS, process.signal(signals::signal_by_name_or_value("KILL").unwrap() as isize));
                    process.set_timeout(None);
                    return_if_err!(ERR_EXIT_STATUS, process.wait());
                    137
                }
            }
        }
    }
}
<|endoftext|>