<commit_before>//! Tests for setting custom rustdoc flags.

use cargo_test_support::project;

#[cargo_test]
fn parses_env() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("doc -v")
        .env("RUSTDOCFLAGS", "--cfg=foo")
        .with_stderr_contains("[RUNNING] `rustdoc [..] --cfg=foo[..]`")
        .run();
}

#[cargo_test]
fn parses_config() {
    let p = project()
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            r#"
            [build]
            rustdocflags = ["--cfg", "foo"]
        "#,
        )
        .build();

    p.cargo("doc -v")
        .with_stderr_contains("[RUNNING] `rustdoc [..] --cfg foo[..]`")
        .run();
}

#[cargo_test]
fn bad_flags() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("doc")
        .env("RUSTDOCFLAGS", "--bogus")
        .with_status(101)
        .with_stderr_contains("[..]bogus[..]")
        .run();
}

#[cargo_test]
fn rerun() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo").run();
    p.cargo("doc")
        .env("RUSTDOCFLAGS", "--cfg=foo")
        .with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
        .run();
    p.cargo("doc")
        .env("RUSTDOCFLAGS", "--cfg=bar")
        .with_stderr(
            "\
[DOCUMENTING] foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdocflags_passed_to_rustdoc_through_cargo_test() {
    let p = project()
        .file(
            "src/lib.rs",
            r#"
            //! ```
            //! assert!(cfg!(do_not_choke));
            //! ```
        "#,
        )
        .build();

    p.cargo("test --doc")
        .env("RUSTDOCFLAGS", "--cfg do_not_choke")
        .run();
}

#[cargo_test]
fn rustdocflags_passed_to_rustdoc_through_cargo_test_only_once() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("test --doc")
        .env("RUSTDOCFLAGS", "--markdown-no-toc")
        .run();
}

#[cargo_test]
fn rustdocflags_misspelled() {
    let p = project().file("src/main.rs", "fn main() { }").build();

    p.cargo("doc")
        .env("RUSTDOC_FLAGS", "foo")
        .with_stderr_contains("[WARNING] Cargo does not read `RUSTDOC_FLAGS` environment variable. Did you mean `RUSTDOCFLAGS`?")
        .run();
}
<commit_msg>Auto merge of #8706 - ehuss:flag-whitespace-test, r=alexcrichton<commit_after>//! Tests for setting custom rustdoc flags.

use cargo_test_support::project;

#[cargo_test]
fn parses_env() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("doc -v")
        .env("RUSTDOCFLAGS", "--cfg=foo")
        .with_stderr_contains("[RUNNING] `rustdoc [..] --cfg=foo[..]`")
        .run();
}

#[cargo_test]
fn parses_config() {
    let p = project()
        .file("src/lib.rs", "")
        .file(
            ".cargo/config",
            r#"
            [build]
            rustdocflags = ["--cfg", "foo"]
        "#,
        )
        .build();

    p.cargo("doc -v")
        .with_stderr_contains("[RUNNING] `rustdoc [..] --cfg foo[..]`")
        .run();
}

#[cargo_test]
fn bad_flags() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("doc")
        .env("RUSTDOCFLAGS", "--bogus")
        .with_status(101)
        .with_stderr_contains("[..]bogus[..]")
        .run();
}

#[cargo_test]
fn rerun() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo").run();
    p.cargo("doc")
        .env("RUSTDOCFLAGS", "--cfg=foo")
        .with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
        .run();
    p.cargo("doc")
        .env("RUSTDOCFLAGS", "--cfg=bar")
        .with_stderr(
            "\
[DOCUMENTING] foo v0.0.1 ([..])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#[cargo_test]
fn rustdocflags_passed_to_rustdoc_through_cargo_test() {
    let p = project()
        .file(
            "src/lib.rs",
            r#"
            //! ```
            //! assert!(cfg!(do_not_choke));
            //! ```
        "#,
        )
        .build();

    p.cargo("test --doc")
        .env("RUSTDOCFLAGS", "--cfg do_not_choke")
        .run();
}

#[cargo_test]
fn rustdocflags_passed_to_rustdoc_through_cargo_test_only_once() {
    let p = project().file("src/lib.rs", "").build();

    p.cargo("test --doc")
        .env("RUSTDOCFLAGS", "--markdown-no-toc")
        .run();
}

#[cargo_test]
fn rustdocflags_misspelled() {
    let p = project().file("src/main.rs", "fn main() { }").build();

    p.cargo("doc")
        .env("RUSTDOC_FLAGS", "foo")
        .with_stderr_contains("[WARNING] Cargo does not read `RUSTDOC_FLAGS` environment variable. Did you mean `RUSTDOCFLAGS`?")
        .run();
}

#[cargo_test]
fn whitespace() {
    // Checks behavior of different whitespace characters.
    let p = project().file("src/lib.rs", "").build();

    // "too many operands"
    p.cargo("doc")
        .env("RUSTDOCFLAGS", "--crate-version this has spaces")
        .with_stderr_contains("[ERROR] could not document `foo`")
        .with_status(101)
        .run();

    const SPACED_VERSION: &str = "a\nb\tc\u{00a0}d";
    p.cargo("doc")
        .env(
            "RUSTDOCFLAGS",
            format!("--crate-version {}", SPACED_VERSION),
        )
        .run();

    let contents = p.read_file("target/doc/foo/index.html");
    assert!(contents.contains(SPACED_VERSION));
}
<|endoftext|>


<commit_before>#![warn(rust_2018_idioms)]

use tokio::io::{AsyncRead, ReadBuf};
use tokio_test::assert_ready;
use tokio_test::task;
use tokio_util::codec::{Decoder, FramedRead};

use bytes::{Buf, BytesMut};
use futures::Stream;
use std::collections::VecDeque;
use std::io;
use std::pin::Pin;
use std::task::Poll::{Pending, Ready};
use std::task::{Context, Poll};

macro_rules! mock {
    ($($x:expr,)*) => {{
        let mut v = VecDeque::new();
        v.extend(vec![$($x),*]);
        Mock { calls: v }
    }};
}

macro_rules! assert_read {
    ($e:expr, $n:expr) => {{
        let val = assert_ready!($e);
        assert_eq!(val.unwrap().unwrap(), $n);
    }};
}

macro_rules! pin {
    ($id:ident) => {
        Pin::new(&mut $id)
    };
}

struct U32Decoder;

impl Decoder for U32Decoder {
    type Item = u32;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<u32>> {
        if buf.len() < 4 {
            return Ok(None);
        }

        let n = buf.split_to(4).get_u32();
        Ok(Some(n))
    }
}

#[test]
fn read_multi_frame_in_packet() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02".to_vec()),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert_read!(pin!(framed).poll_next(cx), 2);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

#[test]
fn read_multi_frame_across_packets() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00\x00\x00".to_vec()),
        Ok(b"\x00\x00\x00\x01".to_vec()),
        Ok(b"\x00\x00\x00\x02".to_vec()),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert_read!(pin!(framed).poll_next(cx), 2);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

#[test]
fn read_not_ready() {
    let mut task = task::spawn(());
    let mock = mock! {
        Err(io::Error::new(io::ErrorKind::WouldBlock, "")),
        Ok(b"\x00\x00\x00\x00".to_vec()),
        Ok(b"\x00\x00\x00\x01".to_vec()),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert!(pin!(framed).poll_next(cx).is_pending());
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

#[test]
fn read_partial_then_not_ready() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00".to_vec()),
        Err(io::Error::new(io::ErrorKind::WouldBlock, "")),
        Ok(b"\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02".to_vec()),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert!(pin!(framed).poll_next(cx).is_pending());
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert_read!(pin!(framed).poll_next(cx), 2);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

#[test]
fn read_err() {
    let mut task = task::spawn(());
    let mock = mock! {
        Err(io::Error::new(io::ErrorKind::Other, "")),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert_eq!(
            io::ErrorKind::Other,
            assert_ready!(pin!(framed).poll_next(cx))
                .unwrap()
                .unwrap_err()
                .kind()
        )
    });
}

#[test]
fn read_partial_then_err() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00".to_vec()),
        Err(io::Error::new(io::ErrorKind::Other, "")),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert_eq!(
            io::ErrorKind::Other,
            assert_ready!(pin!(framed).poll_next(cx))
                .unwrap()
                .unwrap_err()
                .kind()
        )
    });
}

#[test]
fn read_partial_would_block_then_err() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00".to_vec()),
        Err(io::Error::new(io::ErrorKind::WouldBlock, "")),
        Err(io::Error::new(io::ErrorKind::Other, "")),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert!(pin!(framed).poll_next(cx).is_pending());
        assert_eq!(
            io::ErrorKind::Other,
            assert_ready!(pin!(framed).poll_next(cx))
                .unwrap()
                .unwrap_err()
                .kind()
        )
    });
}

#[test]
fn huge_size() {
    let mut task = task::spawn(());
    let data = [0; 32 * 1024];
    let mut framed = FramedRead::new(Slice(&data[..]), BigDecoder);

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });

    struct BigDecoder;

    impl Decoder for BigDecoder {
        type Item = u32;
        type Error = io::Error;

        fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<u32>> {
            if buf.len() < 32 * 1024 {
                return Ok(None);
            }
            buf.advance(32 * 1024);
            Ok(Some(0))
        }
    }
}

#[test]
fn data_remaining_is_error() {
    let mut task = task::spawn(());
    let slice = Slice(&[0; 5]);
    let mut framed = FramedRead::new(slice, U32Decoder);

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).unwrap().is_err());
    });
}

#[test]
fn multi_frames_on_eof() {
    let mut task = task::spawn(());
    struct MyDecoder(Vec<u32>);

    impl Decoder for MyDecoder {
        type Item = u32;
        type Error = io::Error;

        fn decode(&mut self, _buf: &mut BytesMut) -> io::Result<Option<u32>> {
            unreachable!();
        }

        fn decode_eof(&mut self, _buf: &mut BytesMut) -> io::Result<Option<u32>> {
            if self.0.is_empty() {
                return Ok(None);
            }

            Ok(Some(self.0.remove(0)))
        }
    }

    let mut framed = FramedRead::new(mock!(), MyDecoder(vec![0, 1, 2, 3]));

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert_read!(pin!(framed).poll_next(cx), 2);
        assert_read!(pin!(framed).poll_next(cx), 3);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

// ===== Mock ======

struct Mock {
    calls: VecDeque<io::Result<Vec<u8>>>,
}

impl AsyncRead for Mock {
    fn poll_read(
        mut self: Pin<&mut Self>,
        _cx: &mut Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<io::Result<()>> {
        use io::ErrorKind::WouldBlock;

        match self.calls.pop_front() {
            Some(Ok(data)) => {
                debug_assert!(buf.remaining() >= data.len());
                buf.append(&data);
                Ready(Ok(()))
            }
            Some(Err(ref e)) if e.kind() == WouldBlock => Pending,
            Some(Err(e)) => Ready(Err(e)),
            None => Ready(Ok(())),
        }
    }
}

// TODO this newtype is necessary because `&[u8]` does not currently implement `AsyncRead`
struct Slice<'a>(&'a [u8]);

impl AsyncRead for Slice<'_> {
    fn poll_read(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<io::Result<()>> {
        Pin::new(&mut self.0).poll_read(cx, buf)
    }
}
<commit_msg>util: remove Slice wrapper (#2847)<commit_after>#![warn(rust_2018_idioms)]

use tokio::io::{AsyncRead, ReadBuf};
use tokio_test::assert_ready;
use tokio_test::task;
use tokio_util::codec::{Decoder, FramedRead};

use bytes::{Buf, BytesMut};
use futures::Stream;
use std::collections::VecDeque;
use std::io;
use std::pin::Pin;
use std::task::Poll::{Pending, Ready};
use std::task::{Context, Poll};

macro_rules! mock {
    ($($x:expr,)*) => {{
        let mut v = VecDeque::new();
        v.extend(vec![$($x),*]);
        Mock { calls: v }
    }};
}

macro_rules! assert_read {
    ($e:expr, $n:expr) => {{
        let val = assert_ready!($e);
        assert_eq!(val.unwrap().unwrap(), $n);
    }};
}

macro_rules! pin {
    ($id:ident) => {
        Pin::new(&mut $id)
    };
}

struct U32Decoder;

impl Decoder for U32Decoder {
    type Item = u32;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<u32>> {
        if buf.len() < 4 {
            return Ok(None);
        }

        let n = buf.split_to(4).get_u32();
        Ok(Some(n))
    }
}

#[test]
fn read_multi_frame_in_packet() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02".to_vec()),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert_read!(pin!(framed).poll_next(cx), 2);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

#[test]
fn read_multi_frame_across_packets() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00\x00\x00".to_vec()),
        Ok(b"\x00\x00\x00\x01".to_vec()),
        Ok(b"\x00\x00\x00\x02".to_vec()),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert_read!(pin!(framed).poll_next(cx), 2);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

#[test]
fn read_not_ready() {
    let mut task = task::spawn(());
    let mock = mock! {
        Err(io::Error::new(io::ErrorKind::WouldBlock, "")),
        Ok(b"\x00\x00\x00\x00".to_vec()),
        Ok(b"\x00\x00\x00\x01".to_vec()),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert!(pin!(framed).poll_next(cx).is_pending());
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

#[test]
fn read_partial_then_not_ready() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00".to_vec()),
        Err(io::Error::new(io::ErrorKind::WouldBlock, "")),
        Ok(b"\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02".to_vec()),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert!(pin!(framed).poll_next(cx).is_pending());
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert_read!(pin!(framed).poll_next(cx), 2);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

#[test]
fn read_err() {
    let mut task = task::spawn(());
    let mock = mock! {
        Err(io::Error::new(io::ErrorKind::Other, "")),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert_eq!(
            io::ErrorKind::Other,
            assert_ready!(pin!(framed).poll_next(cx))
                .unwrap()
                .unwrap_err()
                .kind()
        )
    });
}

#[test]
fn read_partial_then_err() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00".to_vec()),
        Err(io::Error::new(io::ErrorKind::Other, "")),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert_eq!(
            io::ErrorKind::Other,
            assert_ready!(pin!(framed).poll_next(cx))
                .unwrap()
                .unwrap_err()
                .kind()
        )
    });
}

#[test]
fn read_partial_would_block_then_err() {
    let mut task = task::spawn(());
    let mock = mock! {
        Ok(b"\x00\x00".to_vec()),
        Err(io::Error::new(io::ErrorKind::WouldBlock, "")),
        Err(io::Error::new(io::ErrorKind::Other, "")),
    };
    let mut framed = FramedRead::new(mock, U32Decoder);

    task.enter(|cx, _| {
        assert!(pin!(framed).poll_next(cx).is_pending());
        assert_eq!(
            io::ErrorKind::Other,
            assert_ready!(pin!(framed).poll_next(cx))
                .unwrap()
                .unwrap_err()
                .kind()
        )
    });
}

#[test]
fn huge_size() {
    let mut task = task::spawn(());
    let data = &[0; 32 * 1024][..];
    let mut framed = FramedRead::new(data, BigDecoder);

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });

    struct BigDecoder;

    impl Decoder for BigDecoder {
        type Item = u32;
        type Error = io::Error;

        fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<u32>> {
            if buf.len() < 32 * 1024 {
                return Ok(None);
            }
            buf.advance(32 * 1024);
            Ok(Some(0))
        }
    }
}

#[test]
fn data_remaining_is_error() {
    let mut task = task::spawn(());
    let slice = &[0; 5][..];
    let mut framed = FramedRead::new(slice, U32Decoder);

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).unwrap().is_err());
    });
}

#[test]
fn multi_frames_on_eof() {
    let mut task = task::spawn(());
    struct MyDecoder(Vec<u32>);

    impl Decoder for MyDecoder {
        type Item = u32;
        type Error = io::Error;

        fn decode(&mut self, _buf: &mut BytesMut) -> io::Result<Option<u32>> {
            unreachable!();
        }

        fn decode_eof(&mut self, _buf: &mut BytesMut) -> io::Result<Option<u32>> {
            if self.0.is_empty() {
                return Ok(None);
            }

            Ok(Some(self.0.remove(0)))
        }
    }

    let mut framed = FramedRead::new(mock!(), MyDecoder(vec![0, 1, 2, 3]));

    task.enter(|cx, _| {
        assert_read!(pin!(framed).poll_next(cx), 0);
        assert_read!(pin!(framed).poll_next(cx), 1);
        assert_read!(pin!(framed).poll_next(cx), 2);
        assert_read!(pin!(framed).poll_next(cx), 3);
        assert!(assert_ready!(pin!(framed).poll_next(cx)).is_none());
    });
}

// ===== Mock ======

struct Mock {
    calls: VecDeque<io::Result<Vec<u8>>>,
}

impl AsyncRead for Mock {
    fn poll_read(
        mut self: Pin<&mut Self>,
        _cx: &mut Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<io::Result<()>> {
        use io::ErrorKind::WouldBlock;

        match self.calls.pop_front() {
            Some(Ok(data)) => {
                debug_assert!(buf.remaining() >= data.len());
                buf.append(&data);
                Ready(Ok(()))
            }
            Some(Err(ref e)) if e.kind() == WouldBlock => Pending,
            Some(Err(e)) => Ready(Err(e)),
            None => Ready(Ok(())),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod census;
pub mod service;
pub mod signals;
pub mod service_updater;

use std::net::SocketAddr;
use std::thread;
use std::sync::{Arc, RwLock};
use std::time::Duration;

use butterfly;
use butterfly::member::Member;
use butterfly::trace::Trace;
use butterfly::rumor::service::Service as ServiceRumor;
use butterfly::server::timing::Timing;
use hcore::crypto::{default_cache_key_path, SymKey};
use hcore::service::ServiceGroup;
use time::{SteadyTime, Duration as TimeDuration};

use self::service_updater::ServiceUpdater;
use error::{Error, Result};
use config::{gconfig, UpdateStrategy, Topology};
use manager::service::Service;
use manager::census::{CensusUpdate, CensusList, CensusEntry};
use manager::signals::SignalEvent;
use package::Package;
use http_gateway;
use util;

static LOGKEY: &'static str = "MR";

#[derive(Clone)]
pub struct State {
    pub butterfly: butterfly::Server,
    pub census_list: Arc<RwLock<CensusList>>,
    pub services: Arc<RwLock<Vec<Service>>>,
}

impl State {
    pub fn new(butterfly: butterfly::Server) -> Self {
        State {
            butterfly: butterfly,
            census_list: Arc::new(RwLock::new(CensusList::new())),
            services: Arc::new(RwLock::new(Vec::new())),
        }
    }
}

pub struct Manager {
    state: State,
    updater: ServiceUpdater,
}

impl Manager {
    pub fn new() -> Result<Manager> {
        let gossip_addr: SocketAddr = try!(gconfig().gossip_listen().parse());

        let mut member = Member::new();
        member.set_persistent(gconfig().gossip_permanent());
        member.set_swim_port(gossip_addr.port() as i32);
        member.set_gossip_port(gossip_addr.port() as i32);

        let ring_key = match gconfig().ring() {
            &Some(ref ring_with_revision) => {
                outputln!("Joining ring {}", ring_with_revision);
                Some(try!(SymKey::get_pair_for(&ring_with_revision, &default_cache_key_path(None))))
            }
            &None => None,
        };

        let server = try!(butterfly::Server::new(gconfig().gossip_listen(),
                                                 gconfig().gossip_listen(),
                                                 member,
                                                 Trace::default(),
                                                 ring_key,
                                                 None));
        outputln!("Butterfly Member ID {}", server.member_id());
        for peer_addr in gconfig().gossip_peer() {
            let addr: SocketAddr = peer_addr.parse().unwrap();
            let mut peer = Member::new();
            peer.set_address(format!("{}", addr.ip()));
            peer.set_swim_port(addr.port() as i32);
            peer.set_gossip_port(addr.port() as i32);
            server.member_list.add_initial_member(peer);
        }
        Ok(Manager {
            state: State::new(server),
            updater: ServiceUpdater::default(),
        })
    }

    pub fn add_service(&mut self,
                       package: Package,
                       topology: Topology,
                       update_strategy: UpdateStrategy)
                       -> Result<()> {
        let service_group = ServiceGroup::new(package.name.clone(),
                                              gconfig().group().to_string(),
                                              gconfig().organization().clone());
        let hostname = try!(util::sys::hostname());
        let ip = try!(util::sys::ip());
        // TODO: We should do this much earlier, to confirm that the ports we expose are not
        //       bullshit.
        let mut exposes = Vec::new();
        for port in package.exposes().into_iter() {
            let port_num = try!(port.parse::<u32>().map_err(|e| sup_error!(Error::InvalidPort(e))));
            exposes.push(port_num);
        }
        let service_rumor = ServiceRumor::new(self.state.butterfly.member_id(),
                                              service_group.clone(),
                                              hostname,
                                              format!("{}", ip),
                                              exposes);
        self.state.butterfly.insert_service(service_rumor);

        if topology == Topology::Leader || topology == Topology::Initializer {
            // Note - eventually, we need to deal with suitability here. The original implementation
            // didn't have this working either.
            self.state.butterfly.start_election(service_group.clone(), 0, 0);
        }

        let service = try!(Service::new(service_group, package, topology, update_strategy));
        self.updater.add(&service);
        self.state.services.write().expect("Services lock is poisoned!").push(service);
        Ok(())
    }

    pub fn build_census(&mut self, last_update: &CensusUpdate) -> Result<(bool, CensusUpdate)> {
        let update = CensusUpdate::new(self.state.butterfly.service_store.get_update_counter(),
                                       self.state.butterfly.election_store.get_update_counter(),
                                       self.state.butterfly.member_list.get_update_counter());

        if &update != last_update {
            let mut cl = CensusList::new();
            debug!("Updating census from butterfly data");
            self.state.butterfly.service_store.with_keys(|(_service_group, rumors)| {
                for (_member_id, service) in rumors.iter() {
                    let mut ce = CensusEntry::default();
                    ce.populate_from_service(service);
                    cl.insert(String::from(self.state.butterfly.member_id()), ce);
                }
            });
            self.state.butterfly.election_store.with_keys(|(_service_group, rumors)| {
                // We know you have an election, and this is the only key in the hash
                let election = rumors.get("election").unwrap();
                cl.populate_from_election(election);
            });
            self.state.butterfly.member_list.with_members(|member| {
                cl.populate_from_member(member);
                if let Some(health) = self.state.butterfly.member_list.health_of(member) {
                    cl.populate_from_health(member, health);
                }
            });
            *self.state.census_list.write().expect("Census list lock is poisoned!") = cl;
            return Ok((true, update));
        }
        Ok((false, update))
    }

    fn check_for_incoming_signals(&mut self) -> bool {
        match signals::check_for_signal() {
            Some(SignalEvent::Shutdown) => {
                for service in self.state
                    .services
                    .write()
                    .expect("Services lock is poisoned!")
                    .iter_mut() {
                    outputln!("Shutting down {}", service);
                    service.down()
                        .unwrap_or_else(|err| outputln!("Failed to shutdown {}: {}", service, err));
                }
                true
            }
            Some(SignalEvent::Passthrough(signal_code)) => {
                for service in self.state
                    .services
                    .read()
                    .expect("Services lock is poisoned!")
                    .iter() {
                    outputln!("Forwarding signal {} to {}", signal_code, service);
                    if let Err(e) = service.send_signal(signal_code) {
                        outputln!("Failed to send signal {} to {}: {}",
                                  signal_code,
                                  service,
                                  e);
                    }
                }
                false
            }
            None => false,
        }
    }

    /// Walk each service and check if it has an updated package installed via the Update Strategy.
    pub fn check_for_updated_packages(&mut self) {
        for service in self.state.services.write().expect("Services lock is poisoned!").iter_mut() {
            self.updater.check_for_updated_package(service);
        }
    }

    //  * Start butterfly
    //  Loop {
    //    * Check for incoming signals; forward them; shut down if neccessary
    //    * Check if each service needs its package updated
    //      * Update the package
    //    * Check if the Census needs building from Butterfly, or the package changed
    //      * Loop the services, and reconfigure the service from the Census
    //    * Reap any dead children
    //    * Start or restart the services
    //  }
    //
    pub fn run(&mut self) -> Result<()> {
        // Set the global signal handlers
        signals::init();

        outputln!("Starting butterfly on {}", gconfig().gossip_listen());
        try!(self.state.butterfly.start(Timing::default()));
        debug!("butterfly server started");
        outputln!("Starting http-gateway on {}", gconfig().http_listen_addr());
        try!(http_gateway::Server::new(self.state.clone()).start());
        debug!("http-gateway server started");

        // Watch for updates
        let mut last_census_update = CensusUpdate::new(0, 0, 0);

        'services: loop {
            let next_check = SteadyTime::now() + TimeDuration::milliseconds(1000);
            // Check for incoming signals.
            //
            // This takes signals passed to `hab-sup` and either shuts down all the services, or
            // passes the signals through. This functionality is totally going to need a refactor
            // when we get all the way to a single-sup-per-kernel model, since passing all random
            // signals through to all services is most certainly not what you want.
            //
            // This function returns true if we are supposed to shut the system down, false if we
            // can keep going.
            if self.check_for_incoming_signals() {
                outputln!("Habitat thanks you - shutting down!");
                return Ok(());
            }

            // Check for updated packages; this updates the Service to point to the new service
            // struct, and then marks it for restarting.
            self.check_for_updated_packages();

            // Check if any elections need restarting.
            self.state.butterfly.restart_elections();

            // Try and build the census from the gossip data, updating the last_census_update with
            // the resulting checkpoints. The census is our representation of the data produced
            // by Butterfly.
            let (census_updated, ncu) = try!(self.build_census(&last_census_update));
            if census_updated {
                last_census_update = ncu;
            }

            for service in self.state
                .services
                .write()
                .expect("Services lock is poisoned!")
                .iter_mut() {

                // Write out any files we received via butterfly
                let mut service_files_updated = false;
                for (incarnation, filename, body) in self.state
                    .butterfly
                    .service_files_for(&service.service_group_str(),
                                       &service.current_service_files)
                    .into_iter() {
                    let result = service.write_butterfly_service_file(filename, incarnation, body);
                    if service_files_updated == false && result == true {
                        service_files_updated = true;
                    }
                }
                if service_files_updated {
                    service.file_updated();
                }

                // Write out any service configuration we received via butterfly
                let mut service_config_updated = false;
                if let Some((incarnation, config)) = self.state
                    .butterfly
                    .service_config_for(&service.service_group_str(),
                                        service.service_config_incarnation) {
                    service_config_updated = service.write_butterfly_service_config(config);
                    service.service_config_incarnation = Some(incarnation);
                }

                // Reconfigure if neccessary
                if census_updated || service_config_updated {
                    service.reconfigure(&self.state
                        .census_list
                        .read()
                        .expect("Census list lock is poisoned!"));
                }

                // If this service has not been initialized, do so now.
                service.initialize();

                // Reap dead children
                let _ = service.check_process();

                // Start or restart the service
                if service.initialized && (service.needs_restart || service.is_down()) {
                    match service.restart(&self.state
                        .census_list
                        .read()
                        .expect("Census list lock is poisoned!")) {
                        Ok(()) => {}
                        Err(e) => outputln!("Cannot restart service: {}", e),
                    }
                }
            }

            let time_to_wait = next_check - SteadyTime::now();
            thread::sleep(Duration::from_millis(time_to_wait.num_milliseconds() as u64));
        }
    }
}
<commit_msg>Fix unexpectedly long thread sleep in Supervisor's main loop<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod census;
pub mod service;
pub mod signals;
pub mod service_updater;

use std::net::SocketAddr;
use std::thread;
use std::sync::{Arc, RwLock};
use std::time::Duration;

use butterfly;
use butterfly::member::Member;
use butterfly::trace::Trace;
use butterfly::rumor::service::Service as ServiceRumor;
use butterfly::server::timing::Timing;
use hcore::crypto::{default_cache_key_path, SymKey};
use hcore::service::ServiceGroup;
use time::{SteadyTime, Duration as TimeDuration};

use self::service_updater::ServiceUpdater;
use error::{Error, Result};
use config::{gconfig, UpdateStrategy, Topology};
use manager::service::Service;
use manager::census::{CensusUpdate, CensusList, CensusEntry};
use manager::signals::SignalEvent;
use package::Package;
use http_gateway;
use util;

static LOGKEY: &'static str = "MR";

#[derive(Clone)]
pub struct State {
    pub butterfly: butterfly::Server,
    pub census_list: Arc<RwLock<CensusList>>,
    pub services: Arc<RwLock<Vec<Service>>>,
}

impl State {
    pub fn new(butterfly: butterfly::Server) -> Self {
        State {
            butterfly: butterfly,
            census_list: Arc::new(RwLock::new(CensusList::new())),
            services: Arc::new(RwLock::new(Vec::new())),
        }
    }
}

pub struct Manager {
    state: State,
    updater: ServiceUpdater,
}

impl Manager {
    pub fn new() -> Result<Manager> {
        let gossip_addr: SocketAddr = try!(gconfig().gossip_listen().parse());

        let mut member = Member::new();
        member.set_persistent(gconfig().gossip_permanent());
        member.set_swim_port(gossip_addr.port() as i32);
        member.set_gossip_port(gossip_addr.port() as i32);

        let ring_key = match gconfig().ring() {
            &Some(ref ring_with_revision) => {
                outputln!("Joining ring {}", ring_with_revision);
                Some(try!(SymKey::get_pair_for(&ring_with_revision, &default_cache_key_path(None))))
            }
            &None => None,
        };

        let server = try!(butterfly::Server::new(gconfig().gossip_listen(),
                                                 gconfig().gossip_listen(),
                                                 member,
                                                 Trace::default(),
                                                 ring_key,
                                                 None));
        outputln!("Butterfly Member ID {}", server.member_id());
        for peer_addr in gconfig().gossip_peer() {
            let addr: SocketAddr = peer_addr.parse().unwrap();
            let mut peer = Member::new();
            peer.set_address(format!("{}", addr.ip()));
            peer.set_swim_port(addr.port() as i32);
            peer.set_gossip_port(addr.port() as i32);
            server.member_list.add_initial_member(peer);
        }
        Ok(Manager {
            state: State::new(server),
            updater: ServiceUpdater::default(),
        })
    }

    pub fn add_service(&mut self,
                       package: Package,
                       topology: Topology,
                       update_strategy: UpdateStrategy)
                       -> Result<()> {
        let service_group = ServiceGroup::new(package.name.clone(),
                                              gconfig().group().to_string(),
                                              gconfig().organization().clone());
        let hostname = try!(util::sys::hostname());
        let ip = try!(util::sys::ip());
        // TODO: We should do this much earlier, to confirm that the ports we expose are not
        //       bullshit.
        let mut exposes = Vec::new();
        for port in package.exposes().into_iter() {
            let port_num = try!(port.parse::<u32>().map_err(|e| sup_error!(Error::InvalidPort(e))));
            exposes.push(port_num);
        }
        let service_rumor = ServiceRumor::new(self.state.butterfly.member_id(),
                                              service_group.clone(),
                                              hostname,
                                              format!("{}", ip),
                                              exposes);
        self.state.butterfly.insert_service(service_rumor);

        if topology == Topology::Leader || topology == Topology::Initializer {
            // Note - eventually, we need to deal with suitability here. The original implementation
            // didn't have this working either.
            self.state.butterfly.start_election(service_group.clone(), 0, 0);
        }

        let service = try!(Service::new(service_group, package, topology, update_strategy));
        self.updater.add(&service);
        self.state.services.write().expect("Services lock is poisoned!").push(service);
        Ok(())
    }

    pub fn build_census(&mut self, last_update: &CensusUpdate) -> Result<(bool, CensusUpdate)> {
        let update = CensusUpdate::new(self.state.butterfly.service_store.get_update_counter(),
                                       self.state.butterfly.election_store.get_update_counter(),
                                       self.state.butterfly.member_list.get_update_counter());

        if &update != last_update {
            let mut cl = CensusList::new();
            debug!("Updating census from butterfly data");
            self.state.butterfly.service_store.with_keys(|(_service_group, rumors)| {
                for (_member_id, service) in rumors.iter() {
                    let mut ce = CensusEntry::default();
                    ce.populate_from_service(service);
                    cl.insert(String::from(self.state.butterfly.member_id()), ce);
                }
            });
            self.state.butterfly.election_store.with_keys(|(_service_group, rumors)| {
                // We know you have an election, and this is the only key in the hash
                let election = rumors.get("election").unwrap();
                cl.populate_from_election(election);
            });
            self.state.butterfly.member_list.with_members(|member| {
                cl.populate_from_member(member);
                if let Some(health) = self.state.butterfly.member_list.health_of(member) {
                    cl.populate_from_health(member, health);
                }
            });
            *self.state.census_list.write().expect("Census list lock is poisoned!") = cl;
            return Ok((true, update));
        }
        Ok((false, update))
    }

    fn check_for_incoming_signals(&mut self) -> bool {
        match signals::check_for_signal() {
            Some(SignalEvent::Shutdown) => {
                for service in self.state
                    .services
                    .write()
                    .expect("Services lock is poisoned!")
                    .iter_mut() {
                    outputln!("Shutting down {}", service);
                    service.down()
                        .unwrap_or_else(|err| outputln!("Failed to shutdown {}: {}", service, err));
                }
                true
            }
            Some(SignalEvent::Passthrough(signal_code)) => {
                for service in self.state
                    .services
                    .read()
                    .expect("Services lock is poisoned!")
                    .iter() {
                    outputln!("Forwarding signal {} to {}", signal_code, service);
                    if let Err(e) = service.send_signal(signal_code) {
                        outputln!("Failed to send signal {} to {}: {}",
                                  signal_code,
                                  service,
                                  e);
                    }
                }
                false
            }
            None => false,
        }
    }

    /// Walk each service and check if it has an updated package installed via the Update Strategy.
    pub fn check_for_updated_packages(&mut self) {
        for service in self.state.services.write().expect("Services lock is poisoned!").iter_mut() {
            self.updater.check_for_updated_package(service);
        }
    }

    //  * Start butterfly
    //  Loop {
    //    * Check for incoming signals; forward them; shut down if neccessary
    //    * Check if each service needs its package updated
    //      * Update the package
    //    * Check if the Census needs building from Butterfly, or the package changed
    //      * Loop the services, and reconfigure the service from the Census
    //    * Reap any dead children
    //    * Start or restart the services
    //  }
    //
    pub fn run(&mut self) -> Result<()> {
        // Set the global signal handlers
        signals::init();

        outputln!("Starting butterfly on {}", gconfig().gossip_listen());
        try!(self.state.butterfly.start(Timing::default()));
        debug!("butterfly server started");
        outputln!("Starting http-gateway on {}", gconfig().http_listen_addr());
        try!(http_gateway::Server::new(self.state.clone()).start());
        debug!("http-gateway server started");

        // Watch for updates
        let mut last_census_update = CensusUpdate::new(0, 0, 0);

        'services: loop {
            let next_check = SteadyTime::now() + TimeDuration::milliseconds(1000);
            // Check for incoming signals.
            //
            // This takes signals passed to `hab-sup` and either shuts down all the services, or
            // passes the signals through. This functionality is totally going to need a refactor
            // when we get all the way to a single-sup-per-kernel model, since passing all random
            // signals through to all services is most certainly not what you want.
            //
            // This function returns true if we are supposed to shut the system down, false if we
            // can keep going.
            if self.check_for_incoming_signals() {
                outputln!("Habitat thanks you - shutting down!");
                return Ok(());
            }

            // Check for updated packages; this updates the Service to point to the new service
            // struct, and then marks it for restarting.
            self.check_for_updated_packages();

            // Check if any elections need restarting.
            self.state.butterfly.restart_elections();

            // Try and build the census from the gossip data, updating the last_census_update with
            // the resulting checkpoints. The census is our representation of the data produced
            // by Butterfly.
            let (census_updated, ncu) = try!(self.build_census(&last_census_update));
            if census_updated {
                last_census_update = ncu;
            }

            for service in self.state
                .services
                .write()
                .expect("Services lock is poisoned!")
                .iter_mut() {

                // Write out any files we received via butterfly
                let mut service_files_updated = false;
                for (incarnation, filename, body) in
                    self.state
                        .butterfly
                        .service_files_for(&service.service_group_str(),
                                           &service.current_service_files)
                        .into_iter() {
                    let result = service.write_butterfly_service_file(filename, incarnation, body);
                    if service_files_updated == false && result == true {
                        service_files_updated = true;
                    }
                }
                if service_files_updated {
                    service.file_updated();
                }

                // Write out any service configuration we received via butterfly
                let mut service_config_updated = false;
                if let Some((incarnation, config)) =
                    self.state
                        .butterfly
                        .service_config_for(&service.service_group_str(),
                                            service.service_config_incarnation) {
                    service_config_updated = service.write_butterfly_service_config(config);
                    service.service_config_incarnation = Some(incarnation);
                }

                // Reconfigure if neccessary
                if census_updated || service_config_updated {
                    service.reconfigure(&self.state
                        .census_list
                        .read()
                        .expect("Census list lock is poisoned!"));
                }

                // If this service has not been initialized, do so now.
                service.initialize();

                // Reap dead children
                let _ = service.check_process();

                // Start or restart the service
                if service.initialized && (service.needs_restart || service.is_down()) {
                    match service.restart(&self.state
                        .census_list
                        .read()
                        .expect("Census list lock is poisoned!")) {
                        Ok(()) => {}
                        Err(e) => outputln!("Cannot restart service: {}", e),
                    }
                }
            }

            let time_to_wait = next_check - SteadyTime::now();
            if time_to_wait.num_milliseconds() > 0 {
                thread::sleep(Duration::from_millis(time_to_wait.num_milliseconds() as u64));
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::result;

use futures::sync::oneshot;
use hyper::{Response, StatusCode};

use http_service::{empty_response, json_fault_message, json_response};
use request::{ParsedRequest, SyncRequest};
use request::sync::GenerateResponse;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub enum BootSourceType {
    LocalImage,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct LocalImage {
    pub kernel_image_path: String,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct BootSourceBody {
    boot_source_id: String,
    source_type: BootSourceType,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub local_image: Option<LocalImage>,
    // drive_boot to be added later
    // network_boot to be added later
    #[serde(skip_serializing_if = "Option::is_none")]
    pub boot_args: Option<String>,
}

#[derive(Debug)]
pub enum PutBootSourceConfigError {
    InvalidKernelPath,
    InvalidKernelCommandLine,
}

impl GenerateResponse for PutBootSourceConfigError {
    fn generate_response(&self) -> Response {
        use self::PutBootSourceConfigError::*;
        match *self {
            InvalidKernelPath => json_response(
                StatusCode::BadRequest,
                json_fault_message("The kernel path is invalid!"),
            ),
            InvalidKernelCommandLine => json_response(
                StatusCode::BadRequest,
                json_fault_message("The kernel command line is invalid!"),
            ),
        }
    }
}

pub enum PutBootSourceOutcome {
    Created,
    Updated,
    Error(PutBootSourceConfigError),
}

impl GenerateResponse for PutBootSourceOutcome {
    fn generate_response(&self) -> Response {
        use self::PutBootSourceOutcome::*;
        match *self {
            Created => empty_response(StatusCode::Created),
            Updated => empty_response(StatusCode::NoContent),
            Error(ref e) => e.generate_response(),
        }
    }
}

impl BootSourceBody {
    pub fn into_parsed_request(self) -> result::Result<ParsedRequest, String> {
        let (sender, receiver) = oneshot::channel();
        Ok(ParsedRequest::Sync(
            SyncRequest::PutBootSource(self, sender),
            receiver,
        ))
    }
}
<commit_msg>api_server: add unit tests to boot_source.rs<commit_after>use std::result;

use futures::sync::oneshot;
use hyper::{Response, StatusCode};

use http_service::{empty_response, json_fault_message, json_response};
use request::{ParsedRequest, SyncRequest};
use request::sync::GenerateResponse;

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub enum BootSourceType {
    LocalImage,
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct LocalImage {
    pub kernel_image_path: String,
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct BootSourceBody {
    boot_source_id: String,
    source_type: BootSourceType,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub local_image: Option<LocalImage>,
    // drive_boot to be added later
    // network_boot to be added later
    #[serde(skip_serializing_if = "Option::is_none")]
    pub boot_args: Option<String>,
}

#[derive(Debug)]
pub enum PutBootSourceConfigError {
    InvalidKernelPath,
    InvalidKernelCommandLine,
}

impl GenerateResponse for PutBootSourceConfigError {
    fn generate_response(&self) -> Response {
        use self::PutBootSourceConfigError::*;
        match *self {
            InvalidKernelPath => json_response(
                StatusCode::BadRequest,
                json_fault_message("The kernel path is invalid!"),
            ),
            InvalidKernelCommandLine => json_response(
                StatusCode::BadRequest,
                json_fault_message("The kernel command line is invalid!"),
            ),
        }
    }
}

pub enum PutBootSourceOutcome {
    Created,
    Updated,
    Error(PutBootSourceConfigError),
}

impl GenerateResponse for PutBootSourceOutcome {
    fn generate_response(&self) -> Response {
        use self::PutBootSourceOutcome::*;
        match *self {
            Created => empty_response(StatusCode::Created),
            Updated => empty_response(StatusCode::NoContent),
            Error(ref e) => e.generate_response(),
        }
    }
}

impl BootSourceBody {
    pub fn into_parsed_request(self) -> result::Result<ParsedRequest, String> {
        let (sender, receiver) = oneshot::channel();
        Ok(ParsedRequest::Sync(
            SyncRequest::PutBootSource(self, sender),
            receiver,
        ))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generate_response_put_boot_source_config_error() {
        assert_eq!(PutBootSourceConfigError::InvalidKernelPath.generate_response().status(),
                   StatusCode::BadRequest);
        assert_eq!(PutBootSourceConfigError::InvalidKernelCommandLine.generate_response().status(),
                   StatusCode::BadRequest);
    }

    #[test]
    fn test_generate_response_put_boot_source_outcome() {
        assert_eq!(PutBootSourceOutcome::Created.generate_response().status(),
                   StatusCode::Created);
        assert_eq!(PutBootSourceOutcome::Updated.generate_response().status(),
                   StatusCode::NoContent);
        assert_eq!(PutBootSourceOutcome::Error(PutBootSourceConfigError::InvalidKernelPath)
                       .generate_response().status(), StatusCode::BadRequest);
    }

    #[test]
    fn test_into_parsed_request() {
        let body  = BootSourceBody {
            boot_source_id: String::from("/foo/bar"),
            source_type: BootSourceType::LocalImage,
            local_image: Some(LocalImage { kernel_image_path: String::from("/foo/bar") }),
            boot_args: Some(String::from("foobar"))
        };
        let same_body  = BootSourceBody {
            boot_source_id: String::from("/foo/bar"),
            source_type: BootSourceType::LocalImage,
            local_image: Some(LocalImage { kernel_image_path: String::from("/foo/bar") }),
            boot_args: Some(String::from("foobar"))
        };
        let (sender, receiver) = oneshot::channel();
        assert!(body.into_parsed_request().eq(&Ok(ParsedRequest::Sync(
            SyncRequest::PutBootSource(same_body, sender), receiver))))
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 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.
//
// Checks that we correctly codegen extern "C" functions returning structs.
// See issue #52638.

// compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
#![feature(no_core, lang_items)]
#![no_core]

#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }

#[repr(C)]
pub struct Bool {
    b: bool,
}

// CHECK: define i64 @structbool()
// CHECK-NEXT: start:
// CHECK-NEXT: ret i64 72057594037927936
#[no_mangle]
pub extern "C" fn structbool() -> Bool {
    Bool { b: true }
}
<commit_msg>Rollup merge of #52914 - nagisa:sparc-is-sparc’s-own-business, r=alexcrichton<commit_after>// Copyright 2018 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.
//
// Checks that we correctly codegen extern "C" functions returning structs.
// See issue #52638.

// only-sparc64
// compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
#![feature(no_core, lang_items)]
#![no_core]

#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }

#[repr(C)]
pub struct Bool {
    b: bool,
}

// CHECK: define i64 @structbool()
// CHECK-NEXT: start:
// CHECK-NEXT: ret i64 72057594037927936
#[no_mangle]
pub extern "C" fn structbool() -> Bool {
    Bool { b: true }
}
<|endoftext|>


<commit_before>use std::ops::Deref;

use config::gobjects::GObject;
use env::Env;
use library;
use nameutil::*;
use super::*;
use super::imports::Imports;
use super::info_base::InfoBase;
use traits::*;

#[derive(Default)]
pub struct Info {
    pub base: InfoBase,
    pub glib_get_type: Option<String>,
}

impl Deref for Info {
    type Target = InfoBase;

    fn deref(&self) -> &InfoBase {
        &self.base
    }
}

impl Info {
    //TODO: add test in tests/ for panic
    pub fn type_<'a>(&self, library: &'a library::Library) -> &'a library::Record {
        let type_ = library
            .type_(self.type_id)
            .maybe_ref()
            .unwrap_or_else(|| panic!("{} is not a record.", self.full_name));
        type_
    }
}

pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
    info!("Analyzing record {}", obj.name);
    let full_name = obj.name.clone();

    let record_tid = match env.library.find_type(0, &full_name) {
        Some(tid) => tid,
        None => return None,
    };

    let type_ = env.type_(record_tid);

    let name: String = split_namespace_name(&full_name).1.into();

    let record: &library::Record = match type_.maybe_ref() {
        Some(record) => record,
        None => return None,
    };

    let mut imports = Imports::new();
    imports.add("glib::translate::*", None);
    imports.add("ffi", None);
    imports.add("glib_ffi", None);
    imports.add("std::mem", None);
    imports.add("std::ptr", None);
    if let Some(_) = record.glib_get_type {
        imports.add("gobject_ffi", None);
    }

    let mut functions = functions::analyze(
        env,
        &record.functions,
        record_tid,
        obj,
        &mut imports,
        None,
        None,
    );
    let specials = special_functions::extract(&mut functions);

    let (version, deprecated_version) = info_base::versions(
        env,
        obj,
        &functions,
        record.version,
        record.deprecated_version,
    );

    let is_shared = specials.get(&special_functions::Type::Ref).is_some() &&
        specials.get(&special_functions::Type::Unref).is_some();
    if is_shared {
        // `copy` will duplicate a struct while `clone` just adds a reference
        special_functions::unhide(&mut functions, &specials, special_functions::Type::Copy);
    };

    special_functions::analyze_imports(&specials, &mut imports);

    //don't `use` yourself
    imports.remove(&name);

    imports.clean_glib(env);

    let base = InfoBase {
        full_name: full_name,
        type_id: record_tid,
        name: name,
        functions: functions,
        specials: specials,
        imports: imports,
        version: version,
        deprecated_version: deprecated_version,
        cfg_condition: obj.cfg_condition.clone(),
        concurrency: obj.concurrency,
    };

    let info = Info { base: base, glib_get_type: record.glib_get_type.clone() };

    Some(info)
}
<commit_msg>Minor rustfmt fixup<commit_after>use std::ops::Deref;

use config::gobjects::GObject;
use env::Env;
use library;
use nameutil::*;
use super::*;
use super::imports::Imports;
use super::info_base::InfoBase;
use traits::*;

#[derive(Default)]
pub struct Info {
    pub base: InfoBase,
    pub glib_get_type: Option<String>,
}

impl Deref for Info {
    type Target = InfoBase;

    fn deref(&self) -> &InfoBase {
        &self.base
    }
}

impl Info {
    //TODO: add test in tests/ for panic
    pub fn type_<'a>(&self, library: &'a library::Library) -> &'a library::Record {
        let type_ = library
            .type_(self.type_id)
            .maybe_ref()
            .unwrap_or_else(|| panic!("{} is not a record.", self.full_name));
        type_
    }
}

pub fn new(env: &Env, obj: &GObject) -> Option<Info> {
    info!("Analyzing record {}", obj.name);
    let full_name = obj.name.clone();

    let record_tid = match env.library.find_type(0, &full_name) {
        Some(tid) => tid,
        None => return None,
    };

    let type_ = env.type_(record_tid);

    let name: String = split_namespace_name(&full_name).1.into();

    let record: &library::Record = match type_.maybe_ref() {
        Some(record) => record,
        None => return None,
    };

    let mut imports = Imports::new();
    imports.add("glib::translate::*", None);
    imports.add("ffi", None);
    imports.add("glib_ffi", None);
    imports.add("std::mem", None);
    imports.add("std::ptr", None);
    if let Some(_) = record.glib_get_type {
        imports.add("gobject_ffi", None);
    }

    let mut functions = functions::analyze(
        env,
        &record.functions,
        record_tid,
        obj,
        &mut imports,
        None,
        None,
    );
    let specials = special_functions::extract(&mut functions);

    let (version, deprecated_version) = info_base::versions(
        env,
        obj,
        &functions,
        record.version,
        record.deprecated_version,
    );

    let is_shared = specials.get(&special_functions::Type::Ref).is_some() &&
        specials.get(&special_functions::Type::Unref).is_some();
    if is_shared {
        // `copy` will duplicate a struct while `clone` just adds a reference
        special_functions::unhide(&mut functions, &specials, special_functions::Type::Copy);
    };

    special_functions::analyze_imports(&specials, &mut imports);

    //don't `use` yourself
    imports.remove(&name);

    imports.clean_glib(env);

    let base = InfoBase {
        full_name: full_name,
        type_id: record_tid,
        name: name,
        functions: functions,
        specials: specials,
        imports: imports,
        version: version,
        deprecated_version: deprecated_version,
        cfg_condition: obj.cfg_condition.clone(),
        concurrency: obj.concurrency,
    };

    let info = Info {
        base: base,
        glib_get_type: record.glib_get_type.clone(),
    };

    Some(info)
}
<|endoftext|>


<commit_before>use rmm::{
    KILOBYTE,
    MEGABYTE,
    Arch,
    BuddyAllocator,
    BumpAllocator,
    FrameAllocator,
    FrameCount,
    FrameUsage,
    MemoryArea,
    PageMapper,
    PhysicalAddress,
    VirtualAddress,
    X8664Arch,
};

use spin::Mutex;

extern "C" {
    /// The starting byte of the text (code) data segment.
    static mut __text_start: u8;
    /// The ending byte of the text (code) data segment.
    static mut __text_end: u8;
    /// The starting byte of the _.rodata_ (read-only data) segment.
    static mut __rodata_start: u8;
    /// The ending byte of the _.rodata_ (read-only data) segment.
    static mut __rodata_end: u8;
}

unsafe fn page_flags<A: Arch>(virt: VirtualAddress) -> usize {
    let virt_addr = virt.data();

    // Test for being inside a region
    macro_rules! in_section {
        ($n: ident) => {
            virt_addr >= &concat_idents!(__, $n, _start) as *const u8 as usize
                && virt_addr < &concat_idents!(__, $n, _end) as *const u8 as usize
        };
    }

    if in_section!(text) {
        // Remap text read-only, execute
        0
    } else if in_section!(rodata) {
        // Remap rodata read-only, no execute
        A::ENTRY_FLAG_NO_EXEC
    } else {
        // Remap everything else writable, no execute
        A::ENTRY_FLAG_WRITABLE | A::ENTRY_FLAG_NO_EXEC
    }
}

unsafe fn inner<A: Arch>(areas: &'static [MemoryArea], bump_offset: usize) -> BuddyAllocator<A> {
    // First, calculate how much memory we have
    let mut size = 0;
    for area in areas.iter() {
        if area.size > 0 {
            println!("{:X?}", area);
            size += area.size;
        }
    }

    println!("Memory: {} MB", (size + (MEGABYTE - 1)) / MEGABYTE);

    // Create a basic allocator for the first pages
    let mut bump_allocator = BumpAllocator::<A>::new(areas, bump_offset);

    //TODO: memory protection
    {
        let mut mapper = PageMapper::<A, _>::create(
            &mut bump_allocator
        ).expect("failed to create Mapper");

        // Map all physical areas at PHYS_OFFSET
        for area in areas.iter() {
            for i in 0..area.size / A::PAGE_SIZE {
                let phys = area.base.add(i * A::PAGE_SIZE);
                let virt = A::phys_to_virt(phys);
                let flags = page_flags::<A>(virt);
                let flush = mapper.map_phys(
                    virt,
                    phys,
                    flags
                ).expect("failed to map frame");
                flush.ignore(); // Not the active table
            }
        }

        //TODO: remove backwards compatible recursive mapping
        mapper.table().set_entry(511, rmm::PageEntry::new(
            mapper.table().phys().data() | A::ENTRY_FLAG_WRITABLE | A::ENTRY_FLAG_PRESENT | A::ENTRY_FLAG_NO_EXEC
        ));

        println!("Table: {:X}", mapper.table().phys().data());
        for i in 0..512 {
            if let Some(entry) = mapper.table().entry(i) {
                if entry.present() {
                    println!("{}: {:X}", i, entry.data());
                }
            }
        }

        // Use the new table
        mapper.make_current();
    }

    // Create the physical memory map
    let offset = bump_allocator.offset();
    println!("Permanently used: {} KB", (offset + (KILOBYTE - 1)) / KILOBYTE);

    BuddyAllocator::<A>::new(bump_allocator).expect("failed to create BuddyAllocator")
}

pub struct LockedAllocator {
    inner: Mutex<Option<BuddyAllocator<X8664Arch>>>,
}

impl LockedAllocator {
    const fn new() -> Self {
        Self {
            inner: Mutex::new(None)
        }
    }
}

impl FrameAllocator for LockedAllocator {
    unsafe fn allocate(&mut self, count: FrameCount) -> Option<PhysicalAddress> {
        if let Some(ref mut allocator) = *self.inner.lock() {
            allocator.allocate(count)
        } else {
            None
        }
    }

    unsafe fn free(&mut self, address: PhysicalAddress, count: FrameCount) {
        if let Some(ref mut allocator) = *self.inner.lock() {
            allocator.free(address, count)
        }
    }

    unsafe fn usage(&self) -> FrameUsage {
        if let Some(ref allocator) = *self.inner.lock() {
            allocator.usage()
        } else {
            FrameUsage::new(FrameCount::new(0), FrameCount::new(0))
        }
    }
}

static mut AREAS: [MemoryArea; 512] = [MemoryArea {
    base: PhysicalAddress::new(0),
    size: 0,
}; 512];

pub static mut FRAME_ALLOCATOR: LockedAllocator = LockedAllocator::new();

pub unsafe fn mapper_new(table_addr: PhysicalAddress) -> PageMapper<'static, X8664Arch, LockedAllocator> {
    PageMapper::new(table_addr, &mut FRAME_ALLOCATOR)
}

//TODO: global paging lock?
pub unsafe fn mapper_create() -> Option<PageMapper<'static, X8664Arch, LockedAllocator>> {
    PageMapper::create(&mut FRAME_ALLOCATOR)
}

pub unsafe fn mapper_current() -> PageMapper<'static, X8664Arch, LockedAllocator> {
    PageMapper::current(&mut FRAME_ALLOCATOR)
}

pub unsafe fn init(kernel_base: usize, kernel_size: usize) {
    type A = X8664Arch;

    let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
    let kernel_end = kernel_base + kernel_size_aligned;
    println!("kernel_end: {:X}", kernel_end);

    // Copy memory map from bootloader location, and page align it
    let mut area_i = 0;
    let mut bump_offset = 0;
    for i in 0..512 {
        let old = *(0x500 as *const crate::memory::MemoryArea).add(i);
        if old._type != 1 {
            // Not a free area
            continue;
        }

        let mut base = old.base_addr as usize;
        let mut size = old.length as usize;

        // Page align base
        let base_offset = (A::PAGE_SIZE - (base & A::PAGE_OFFSET_MASK)) & A::PAGE_OFFSET_MASK;
        if base_offset > size {
            // Area is too small to page align base
            continue;
        }
        base += base_offset;
        size -= base_offset;

        // Page align size
        size &= !A::PAGE_OFFSET_MASK;
        if size == 0 {
            // Area is zero sized
            continue;
        }

        if base + size < kernel_end {
            // Area is below static kernel data
            bump_offset += size;
        } else if base < kernel_end {
            // Area contains static kernel data
            bump_offset += kernel_end - base;
        }

        AREAS[area_i].base = PhysicalAddress::new(base);
        AREAS[area_i].size = size;
        area_i += 1;
    }

    //TODO: this is a hack to ensure kernel is mapped, even if it uses invalid memory. We need to
    //properly utilize the firmware memory map and not assume 0x100000 and onwards is free
    AREAS[area_i].base = PhysicalAddress::new(kernel_base);
    AREAS[area_i].size = kernel_size_aligned;

    println!("bump_offset: {:X}", bump_offset);

    let allocator = inner::<A>(&AREAS, bump_offset);
    *FRAME_ALLOCATOR.inner.lock() = Some(allocator);
}
<commit_msg>Simplify reserved memory hack<commit_after>use rmm::{
    KILOBYTE,
    MEGABYTE,
    Arch,
    BuddyAllocator,
    BumpAllocator,
    FrameAllocator,
    FrameCount,
    FrameUsage,
    MemoryArea,
    PageMapper,
    PhysicalAddress,
    VirtualAddress,
    X8664Arch,
};

use spin::Mutex;

extern "C" {
    /// The starting byte of the text (code) data segment.
    static mut __text_start: u8;
    /// The ending byte of the text (code) data segment.
    static mut __text_end: u8;
    /// The starting byte of the _.rodata_ (read-only data) segment.
    static mut __rodata_start: u8;
    /// The ending byte of the _.rodata_ (read-only data) segment.
    static mut __rodata_end: u8;
}

unsafe fn page_flags<A: Arch>(virt: VirtualAddress) -> usize {
    let virt_addr = virt.data();

    // Test for being inside a region
    macro_rules! in_section {
        ($n: ident) => {
            virt_addr >= &concat_idents!(__, $n, _start) as *const u8 as usize
                && virt_addr < &concat_idents!(__, $n, _end) as *const u8 as usize
        };
    }

    if in_section!(text) {
        // Remap text read-only, execute
        0
    } else if in_section!(rodata) {
        // Remap rodata read-only, no execute
        A::ENTRY_FLAG_NO_EXEC
    } else {
        // Remap everything else writable, no execute
        A::ENTRY_FLAG_WRITABLE | A::ENTRY_FLAG_NO_EXEC
    }
}

unsafe fn inner<A: Arch>(areas: &'static [MemoryArea], kernel_base: usize, kernel_size_aligned: usize, bump_offset: usize) -> BuddyAllocator<A> {
    // First, calculate how much memory we have
    let mut size = 0;
    for area in areas.iter() {
        if area.size > 0 {
            println!("{:X?}", area);
            size += area.size;
        }
    }

    println!("Memory: {} MB", (size + (MEGABYTE - 1)) / MEGABYTE);

    // Create a basic allocator for the first pages
    let mut bump_allocator = BumpAllocator::<A>::new(areas, bump_offset);

    {
        let mut mapper = PageMapper::<A, _>::create(
            &mut bump_allocator
        ).expect("failed to create Mapper");

        // Map all physical areas at PHYS_OFFSET
        for area in areas.iter() {
            for i in 0..area.size / A::PAGE_SIZE {
                let phys = area.base.add(i * A::PAGE_SIZE);
                let virt = A::phys_to_virt(phys);
                let flags = page_flags::<A>(virt);
                let flush = mapper.map_phys(
                    virt,
                    phys,
                    flags
                ).expect("failed to map frame");
                flush.ignore(); // Not the active table
            }
        }

        //TODO: this is a hack to ensure kernel is mapped, even if it uses invalid memory. We need to
        //properly utilize the firmware memory map and not assume 0x100000 and onwards is free
        for i in 0..kernel_size_aligned / A::PAGE_SIZE {
            let phys = PhysicalAddress::new(kernel_base + i * A::PAGE_SIZE);
            let virt = A::phys_to_virt(phys);
            let flags = page_flags::<A>(virt);
            let flush = mapper.map_phys(
                virt,
                phys,
                flags
            ).expect("failed to map frame");
            flush.ignore(); // Not the active table
        }

        //TODO: remove backwards compatible recursive mapping
        mapper.table().set_entry(511, rmm::PageEntry::new(
            mapper.table().phys().data() | A::ENTRY_FLAG_WRITABLE | A::ENTRY_FLAG_PRESENT | A::ENTRY_FLAG_NO_EXEC
        ));

        println!("Table: {:X}", mapper.table().phys().data());
        for i in 0..512 {
            if let Some(entry) = mapper.table().entry(i) {
                if entry.present() {
                    println!("{}: {:X}", i, entry.data());
                }
            }
        }

        // Use the new table
        mapper.make_current();
    }

    // Create the physical memory map
    let offset = bump_allocator.offset();
    println!("Permanently used: {} KB", (offset + (KILOBYTE - 1)) / KILOBYTE);

    BuddyAllocator::<A>::new(bump_allocator).expect("failed to create BuddyAllocator")
}

pub struct LockedAllocator {
    inner: Mutex<Option<BuddyAllocator<X8664Arch>>>,
}

impl LockedAllocator {
    const fn new() -> Self {
        Self {
            inner: Mutex::new(None)
        }
    }
}

impl FrameAllocator for LockedAllocator {
    unsafe fn allocate(&mut self, count: FrameCount) -> Option<PhysicalAddress> {
        if let Some(ref mut allocator) = *self.inner.lock() {
            allocator.allocate(count)
        } else {
            None
        }
    }

    unsafe fn free(&mut self, address: PhysicalAddress, count: FrameCount) {
        if let Some(ref mut allocator) = *self.inner.lock() {
            allocator.free(address, count)
        }
    }

    unsafe fn usage(&self) -> FrameUsage {
        if let Some(ref allocator) = *self.inner.lock() {
            allocator.usage()
        } else {
            FrameUsage::new(FrameCount::new(0), FrameCount::new(0))
        }
    }
}

static mut AREAS: [MemoryArea; 512] = [MemoryArea {
    base: PhysicalAddress::new(0),
    size: 0,
}; 512];

pub static mut FRAME_ALLOCATOR: LockedAllocator = LockedAllocator::new();

pub unsafe fn mapper_new(table_addr: PhysicalAddress) -> PageMapper<'static, X8664Arch, LockedAllocator> {
    PageMapper::new(table_addr, &mut FRAME_ALLOCATOR)
}

//TODO: global paging lock?
pub unsafe fn mapper_create() -> Option<PageMapper<'static, X8664Arch, LockedAllocator>> {
    PageMapper::create(&mut FRAME_ALLOCATOR)
}

pub unsafe fn mapper_current() -> PageMapper<'static, X8664Arch, LockedAllocator> {
    PageMapper::current(&mut FRAME_ALLOCATOR)
}

pub unsafe fn init(kernel_base: usize, kernel_size: usize) {
    type A = X8664Arch;

    let kernel_size_aligned = ((kernel_size + (A::PAGE_SIZE - 1))/A::PAGE_SIZE) * A::PAGE_SIZE;
    let kernel_end = kernel_base + kernel_size_aligned;
    println!("kernel_end: {:X}", kernel_end);

    // Copy memory map from bootloader location, and page align it
    let mut area_i = 0;
    let mut bump_offset = 0;
    for i in 0..512 {
        let old = *(0x500 as *const crate::memory::MemoryArea).add(i);
        if old._type != 1 {
            // Not a free area
            continue;
        }

        let mut base = old.base_addr as usize;
        let mut size = old.length as usize;

        // Page align base
        let base_offset = (A::PAGE_SIZE - (base & A::PAGE_OFFSET_MASK)) & A::PAGE_OFFSET_MASK;
        if base_offset > size {
            // Area is too small to page align base
            continue;
        }
        base += base_offset;
        size -= base_offset;

        // Page align size
        size &= !A::PAGE_OFFSET_MASK;
        if size == 0 {
            // Area is zero sized
            continue;
        }

        if base + size < kernel_end {
            // Area is below static kernel data
            bump_offset += size;
        } else if base < kernel_end {
            // Area contains static kernel data
            bump_offset += kernel_end - base;
        }

        AREAS[area_i].base = PhysicalAddress::new(base);
        AREAS[area_i].size = size;
        area_i += 1;
    }

    println!("bump_offset: {:X}", bump_offset);

    let allocator = inner::<A>(&AREAS, kernel_base, kernel_size_aligned, bump_offset);
    *FRAME_ALLOCATOR.inner.lock() = Some(allocator);
}
<|endoftext|>


<commit_before>// ignore-tidy-linelength
// ignore-wasm32-bare compiled with panic=abort by default
#![feature(box_syntax)]

fn main() {
    let _x: Box<Vec<u32>> = box Vec::new();
}

// END RUST SOURCE
// START rustc.main.Inline.before.mir
// let mut _0: ();
// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
// let mut _3: ();
// scope 1 {
//   debug _x => _1;
// }
// bb0: {
//   StorageLive(_1);
//   StorageLive(_2);
//   _2 = Box(std::vec::Vec<u32>);
//   (*_2) = const std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4];
// }
// bb1 (cleanup): {
//   resume;
// }
// bb2: {
//   _1 = move _2;
//   StorageDead(_2);
//   _0 = ();
//   drop(_1) -> [return: bb3, unwind: bb1];
// }
// bb3: {
//   StorageDead(_1);
//   return;
// }
// bb4 (cleanup): {
//   _3 = const alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1;
// }
// END rustc.main.Inline.before.mir
// START rustc.main.Inline.after.mir
// let mut _0: ();
// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
// let mut _3: ();
// let mut _4: &mut std::vec::Vec<u32>;
// scope 1 {
//   debug _x => _1;
// }
// scope 2 {
// }
// bb0: {
//   StorageLive(_1);
//   StorageLive(_2);
//   _2 = Box(std::vec::Vec<u32>);
//   _4 = &mut (*_2);
//   ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32>::NEW;
//   ((*_4).1: usize) = const 0usize;
//   _1 = move _2;
//   StorageDead(_2);
//   _0 = ();
//   drop(_1) -> [return: bb2, unwind: bb1];
// }
// bb1 (cleanup): {
//   resume;
// }
// bb2: {
//   StorageDead(_1);
//   return;
// }
// END rustc.main.Inline.after.mir
<commit_msg>Set mir-opt-level to 3 to prevent regressions<commit_after>// ignore-tidy-linelength
// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: -Z mir-opt-level=3
#![feature(box_syntax)]

fn main() {
    let _x: Box<Vec<u32>> = box Vec::new();
}

// END RUST SOURCE
// START rustc.main.Inline.before.mir
// let mut _0: ();
// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
// let mut _3: ();
// scope 1 {
//   debug _x => _1;
// }
// bb0: {
//   StorageLive(_1);
//   StorageLive(_2);
//   _2 = Box(std::vec::Vec<u32>);
//   (*_2) = const std::vec::Vec::<u32>::new() -> [return: bb2, unwind: bb4];
// }
// bb1 (cleanup): {
//   resume;
// }
// bb2: {
//   _1 = move _2;
//   StorageDead(_2);
//   _0 = ();
//   drop(_1) -> [return: bb3, unwind: bb1];
// }
// bb3: {
//   StorageDead(_1);
//   return;
// }
// bb4 (cleanup): {
//   _3 = const alloc::alloc::box_free::<std::vec::Vec<u32>>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>)) -> bb1;
// }
// END rustc.main.Inline.before.mir
// START rustc.main.Inline.after.mir
// let mut _0: ();
// let _1: std::boxed::Box<std::vec::Vec<u32>> as UserTypeProjection { base: UserType(0), projs: [] };
// let mut _2: std::boxed::Box<std::vec::Vec<u32>>;
// let mut _3: ();
// let mut _4: &mut std::vec::Vec<u32>;
// scope 1 {
//   debug _x => _1;
// }
// scope 2 {
// }
// bb0: {
//   StorageLive(_1);
//   StorageLive(_2);
//   _2 = Box(std::vec::Vec<u32>);
//   _4 = &mut (*_2);
//   ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32>::NEW;
//   ((*_4).1: usize) = const 0usize;
//   _1 = move _2;
//   StorageDead(_2);
//   _0 = ();
//   drop(_1) -> [return: bb2, unwind: bb1];
// }
// bb1 (cleanup): {
//   resume;
// }
// bb2: {
//   StorageDead(_1);
//   return;
// }
// END rustc.main.Inline.after.mir
<|endoftext|>


<commit_before>macro_rules! implement {
    {
        impl $type:ident {
            floor = $floor_intrinsic:literal,
            ceil = $ceil_intrinsic:literal,
            round = $round_intrinsic:literal,
            trunc = $trunc_intrinsic:literal,
        }
    } => {
        mod $type {
            #[allow(improper_ctypes)]
            extern "C" {
                #[link_name = $floor_intrinsic]
                fn floor_intrinsic(x: crate::$type) -> crate::$type;
                #[link_name = $ceil_intrinsic]
                fn ceil_intrinsic(x: crate::$type) -> crate::$type;
                #[link_name = $round_intrinsic]
                fn round_intrinsic(x: crate::$type) -> crate::$type;
                #[link_name = $trunc_intrinsic]
                fn trunc_intrinsic(x: crate::$type) -> crate::$type;
            }

            impl crate::$type {
                /// Returns the largest integer less than or equal to each lane.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn floor(self) -> Self {
                    unsafe { floor_intrinsic(self) }
                }

                /// Returns the smallest integer greater than or equal to each lane.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn ceil(self) -> Self {
                    unsafe { ceil_intrinsic(self) }
                }

                /// Returns the nearest integer to each lane. Round half-way cases away from 0.0.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn round(self) -> Self {
                    unsafe { round_intrinsic(self) }
                }

                /// Returns the integer part of each lane.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn trunc(self) -> Self {
                    unsafe { trunc_intrinsic(self) }
                }

                /// Returns the fractional part of each lane.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn fract(self) -> Self {
                    self - self.trunc()
                }
            }
        }
    }
}

implement! {
    impl f32x2 {
        floor = "llvm.floor.v2f32",
        ceil = "llvm.ceil.v2f32",
        round = "llvm.round.v2f32",
        trunc = "llvm.trunc.v2f32",
    }
}

implement! {
    impl f32x4 {
        floor = "llvm.floor.v4f32",
        ceil = "llvm.ceil.v4f32",
        round = "llvm.round.v4f32",
        trunc = "llvm.trunc.v4f32",
    }
}

implement! {
    impl f32x8 {
        floor = "llvm.floor.v8f32",
        ceil = "llvm.ceil.v8f32",
        round = "llvm.round.v8f32",
        trunc = "llvm.trunc.v8f32",
    }
}

implement! {
    impl f32x16 {
        floor = "llvm.floor.v16f32",
        ceil = "llvm.ceil.v16f32",
        round = "llvm.round.v16f32",
        trunc = "llvm.trunc.v16f32",
    }
}

implement! {
    impl f64x2 {
        floor = "llvm.floor.v2f64",
        ceil = "llvm.ceil.v2f64",
        round = "llvm.round.v2f64",
        trunc = "llvm.trunc.v2f64",
    }
}

implement! {
    impl f64x4 {
        floor = "llvm.floor.v4f64",
        ceil = "llvm.ceil.v4f64",
        round = "llvm.round.v4f64",
        trunc = "llvm.trunc.v4f64",
    }
}

implement! {
    impl f64x8 {
        floor = "llvm.floor.v8f64",
        ceil = "llvm.ceil.v8f64",
        round = "llvm.round.v8f64",
        trunc = "llvm.trunc.v8f64",
    }
}
<commit_msg>Add rounding to integers<commit_after>macro_rules! implement {
    {
        impl $type:ident {
            int_type = $int_type:ident,
            floor = $floor_intrinsic:literal,
            ceil = $ceil_intrinsic:literal,
            round = $round_intrinsic:literal,
            trunc = $trunc_intrinsic:literal,
            round_to_int = $round_to_int_intrinsic:literal,
        }
    } => {
        mod $type {
            #[allow(improper_ctypes)]
            extern "C" {
                #[link_name = $floor_intrinsic]
                fn floor_intrinsic(x: crate::$type) -> crate::$type;
                #[link_name = $ceil_intrinsic]
                fn ceil_intrinsic(x: crate::$type) -> crate::$type;
                #[link_name = $round_intrinsic]
                fn round_intrinsic(x: crate::$type) -> crate::$type;
                #[link_name = $trunc_intrinsic]
                fn trunc_intrinsic(x: crate::$type) -> crate::$type;
                #[link_name = $round_to_int_intrinsic]
                fn round_to_int_intrinsic(x: crate::$type) -> crate::$int_type;
            }

            impl crate::$type {
                /// Returns the largest integer less than or equal to each lane.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn floor(self) -> Self {
                    unsafe { floor_intrinsic(self) }
                }

                /// Returns the smallest integer greater than or equal to each lane.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn ceil(self) -> Self {
                    unsafe { ceil_intrinsic(self) }
                }

                /// Returns the nearest integer to each lane. Round half-way cases away from 0.0.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn round(self) -> Self {
                    unsafe { round_intrinsic(self) }
                }

                /// Returns the integer part of each lane.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn trunc(self) -> Self {
                    unsafe { trunc_intrinsic(self) }
                }

                /// Returns the fractional part of each lane.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn fract(self) -> Self {
                    self - self.trunc()
                }

                /// Returns the nearest integer to each lane. Round half-way cases away from 0.0.
                #[must_use = "method returns a new vector and does not mutate the original value"]
                #[inline]
                pub fn round_to_int(self) -> crate::$int_type {
                    unsafe { round_to_int_intrinsic(self) }
                }
            }
        }
    }
}

implement! {
    impl f32x2 {
        int_type = i32x2,
        floor = "llvm.floor.v2f32",
        ceil = "llvm.ceil.v2f32",
        round = "llvm.round.v2f32",
        trunc = "llvm.trunc.v2f32",
        round_to_int = "llvm.lround.i32.v2f32",
    }
}

implement! {
    impl f32x4 {
        int_type = i32x4,
        floor = "llvm.floor.v4f32",
        ceil = "llvm.ceil.v4f32",
        round = "llvm.round.v4f32",
        trunc = "llvm.trunc.v4f32",
        round_to_int = "llvm.lround.i32.v4f32",
    }
}

implement! {
    impl f32x8 {
        int_type = i32x8,
        floor = "llvm.floor.v8f32",
        ceil = "llvm.ceil.v8f32",
        round = "llvm.round.v8f32",
        trunc = "llvm.trunc.v8f32",
        round_to_int = "llvm.lround.i32.v8f32",
    }
}

implement! {
    impl f32x16 {
        int_type = i32x16,
        floor = "llvm.floor.v16f32",
        ceil = "llvm.ceil.v16f32",
        round = "llvm.round.v16f32",
        trunc = "llvm.trunc.v16f32",
        round_to_int = "llvm.lround.i32.v16f32",
    }
}

implement! {
    impl f64x2 {
        int_type = i64x2,
        floor = "llvm.floor.v2f64",
        ceil = "llvm.ceil.v2f64",
        round = "llvm.round.v2f64",
        trunc = "llvm.trunc.v2f64",
        round_to_int = "llvm.lround.i64.v2f64",
    }
}

implement! {
    impl f64x4 {
        int_type = i64x4,
        floor = "llvm.floor.v4f64",
        ceil = "llvm.ceil.v4f64",
        round = "llvm.round.v4f64",
        trunc = "llvm.trunc.v4f64",
        round_to_int = "llvm.lround.i64.v4f64",
    }
}

implement! {
    impl f64x8 {
        int_type = i64x8,
        floor = "llvm.floor.v8f64",
        ceil = "llvm.ceil.v8f64",
        round = "llvm.round.v8f64",
        trunc = "llvm.trunc.v8f64",
        round_to_int = "llvm.lround.i64.v8f64",
    }
}
<|endoftext|>