<commit_before>use super::{MockAnonymousUser, MockCookieUser, MockTokenUser};
use crate::record;
use crate::util::{chaosproxy::ChaosProxy, fresh_schema::FreshSchema};
use cargo_registry::config::{self, DbPoolConfig};
use cargo_registry::{background_jobs::Environment, db::DieselPool, App, Emails};
use cargo_registry_index::testing::UpstreamIndex;
use cargo_registry_index::{Credentials, Repository as WorkerRepository, RepositoryConfig};
use std::{rc::Rc, sync::Arc, time::Duration};

use crate::util::github::{MockGitHubClient, MOCK_GITHUB_DATA};
use diesel::PgConnection;
use reqwest::{blocking::Client, Proxy};
use std::collections::HashSet;
use swirl::Runner;

struct TestAppInner {
    app: Arc<App>,
    // The bomb (if created) needs to be held in scope until the end of the test.
    _bomb: Option<record::Bomb>,
    middle: conduit_middleware::MiddlewareBuilder,
    index: Option<UpstreamIndex>,
    runner: Option<Runner<Environment, DieselPool>>,

    primary_db_chaosproxy: Option<Arc<ChaosProxy>>,
    replica_db_chaosproxy: Option<Arc<ChaosProxy>>,

    // Must be the last field of the struct!
    _fresh_schema: Option<FreshSchema>,
}

impl Drop for TestAppInner {
    fn drop(&mut self) {
        use diesel::prelude::*;
        use swirl::schema::background_jobs::dsl::*;

        // Avoid a double-panic if the test is already failing
        if std::thread::panicking() {
            return;
        }

        // Lazily run any remaining jobs
        if let Some(runner) = &self.runner {
            runner.run_all_pending_jobs().expect("Could not run jobs");
            runner.check_for_failed_jobs().expect("Failed jobs remain");
        }

        // Manually verify that all jobs have completed successfully
        // This will catch any tests that enqueued a job but forgot to initialize the runner
        let conn = self.app.primary_database.get().unwrap();
        let job_count: i64 = background_jobs.count().get_result(&*conn).unwrap();
        assert_eq!(
            0, job_count,
            "Unprocessed or failed jobs remain in the queue"
        );

        // TODO: If a runner was started, obtain the clone from it and ensure its HEAD matches the upstream index HEAD
    }
}

/// A representation of the app and its database transaction
#[derive(Clone)]
pub struct TestApp(Rc<TestAppInner>);

impl TestApp {
    /// Initialize an application with an `Uploader` that panics
    pub fn init() -> TestAppBuilder {
        init_logger();

        TestAppBuilder {
            config: simple_config(),
            proxy: None,
            bomb: None,
            index: None,
            build_job_runner: false,
            test_database: TestDatabase::TestPool,
        }
    }

    /// Initialize the app and a proxy that can record and playback outgoing HTTP requests
    pub fn with_proxy() -> TestAppBuilder {
        Self::init().with_proxy()
    }

    /// Initialize a full application, with a proxy, index, and background worker
    pub fn full() -> TestAppBuilder {
        Self::with_proxy().with_git_index().with_job_runner()
    }

    /// Obtain the database connection and pass it to the closure
    ///
    /// Within each test, the connection pool only has 1 connection so it is necessary to drop the
    /// connection before making any API calls.  Once the closure returns, the connection is
    /// dropped, ensuring it is returned to the pool and available for any future API calls.
    pub fn db<T, F: FnOnce(&PgConnection) -> T>(&self, f: F) -> T {
        let conn = self.0.app.primary_database.get().unwrap();
        f(&conn)
    }

    /// Create a new user with a verified email address in the database and return a mock user
    /// session
    ///
    /// This method updates the database directly
    pub fn db_new_user(&self, username: &str) -> MockCookieUser {
        use cargo_registry::schema::emails;
        use diesel::prelude::*;

        let user = self.db(|conn| {
            let email = "something@example.com";

            let user = crate::new_user(username)
                .create_or_update(None, &self.0.app.emails, conn)
                .unwrap();
            diesel::insert_into(emails::table)
                .values((
                    emails::user_id.eq(user.id),
                    emails::email.eq(email),
                    emails::verified.eq(true),
                ))
                .execute(conn)
                .unwrap();
            user
        });
        MockCookieUser {
            app: self.clone(),
            user,
        }
    }

    /// Obtain a reference to the upstream repository ("the index")
    pub fn upstream_index(&self) -> &UpstreamIndex {
        assert_some!(self.0.index.as_ref())
    }

    /// Obtain a list of crates from the index HEAD
    pub fn crates_from_index_head(&self, crate_name: &str) -> Vec<cargo_registry_index::Crate> {
        self.upstream_index()
            .crates_from_index_head(crate_name)
            .unwrap()
    }

    #[track_caller]
    pub fn run_pending_background_jobs(&self) {
        let runner = &self.0.runner;
        let runner = runner.as_ref().expect("Index has not been initialized");

        runner.run_all_pending_jobs().expect("Could not run jobs");
        runner
            .check_for_failed_jobs()
            .expect("Could not determine if jobs failed");
    }

    /// Obtain a reference to the inner `App` value
    pub fn as_inner(&self) -> &App {
        &self.0.app
    }

    /// Obtain a reference to the inner middleware builder
    pub fn as_middleware(&self) -> &conduit_middleware::MiddlewareBuilder {
        &self.0.middle
    }

    pub(crate) fn primary_db_chaosproxy(&self) -> Arc<ChaosProxy> {
        self.0
            .primary_db_chaosproxy
            .clone()
            .expect("ChaosProxy is not enabled on this test, call with_database during app init")
    }

    pub(crate) fn replica_db_chaosproxy(&self) -> Arc<ChaosProxy> {
        self.0
            .replica_db_chaosproxy
            .clone()
            .expect("ChaosProxy is not enabled on this test, call with_database during app init")
    }
}

/// Defines the type of test database.
pub enum TestDatabase {
    /// Use the fast test database pool
    TestPool,
    /// Use the slow test database pool with a fresh schema that enables ChaosProxy
    /// TODO rewrite comment, uses a database pool
    SlowRealPool { replica: bool },
}

pub struct TestAppBuilder {
    config: config::Server,
    proxy: Option<String>,
    bomb: Option<record::Bomb>,
    index: Option<UpstreamIndex>,
    build_job_runner: bool,
    test_database: TestDatabase,
}

impl TestAppBuilder {
    /// Create a `TestApp` with an empty database
    pub fn empty(mut self) -> (TestApp, MockAnonymousUser) {
        // Run each test inside a fresh database schema, deleted at the end of the test,
        // The schema will be cleared up once the app is dropped.
        let (primary_db_chaosproxy, replica_db_chaosproxy, fresh_schema) =
            if !self.config.use_test_database_pool {
                let fresh_schema = FreshSchema::new(&self.config.db.primary.url);
                let (primary_proxy, url) =
                    ChaosProxy::proxy_database_url(fresh_schema.database_url()).unwrap();
                self.config.db.primary.url = url;

                let replica_proxy = match self.test_database {
                    TestDatabase::SlowRealPool { replica: true } => {
                        let (replica_proxy, url) =
                            ChaosProxy::proxy_database_url(fresh_schema.database_url()).unwrap();
                        self.config.db.replica = Some(DbPoolConfig {
                            url,
                            read_only_mode: true,
                            pool_size: 1,
                            min_idle: None,
                        });
                        Some(replica_proxy)
                    }
                    _ => None,
                };

                (Some(primary_proxy), replica_proxy, Some(fresh_schema))
            } else {
                (None, None, None)
            };

        let (app, middle) = build_app(self.config, self.proxy);

        let runner = if self.build_job_runner {
            let repository_config = RepositoryConfig {
                index_location: UpstreamIndex::url(),
                credentials: Credentials::Missing,
            };
            let index = WorkerRepository::open(&repository_config).expect("Could not clone index");
            let environment = Environment::new(
                index,
                app.config.uploader().clone(),
                app.http_client().clone(),
                None,
            );

            Some(
                Runner::builder(environment)
                    // We only have 1 connection in tests, so trying to run more than
                    // 1 job concurrently will just block
                    .thread_count(1)
                    .connection_pool(app.primary_database.clone())
                    .job_start_timeout(Duration::from_secs(5))
                    .build(),
            )
        } else {
            None
        };

        let test_app_inner = TestAppInner {
            app,
            _fresh_schema: fresh_schema,
            _bomb: self.bomb,
            middle,
            index: self.index,
            runner,
            primary_db_chaosproxy,
            replica_db_chaosproxy,
        };
        let test_app = TestApp(Rc::new(test_app_inner));
        let anon = MockAnonymousUser {
            app: test_app.clone(),
        };
        (test_app, anon)
    }

    /// Create a proxy for use with this app
    pub fn with_proxy(mut self) -> Self {
        let (proxy, bomb) = record::proxy();
        self.proxy = Some(proxy);
        self.bomb = Some(bomb);
        self
    }

    // Create a `TestApp` with a database including a default user
    pub fn with_user(self) -> (TestApp, MockAnonymousUser, MockCookieUser) {
        let (app, anon) = self.empty();
        let user = app.db_new_user("foo");
        (app, anon, user)
    }

    /// Create a `TestApp` with a database including a default user and its token
    pub fn with_token(self) -> (TestApp, MockAnonymousUser, MockCookieUser, MockTokenUser) {
        let (app, anon) = self.empty();
        let user = app.db_new_user("foo");
        let token = user.db_new_token("bar");
        (app, anon, user, token)
    }

    pub fn with_config(mut self, f: impl FnOnce(&mut config::Server)) -> Self {
        f(&mut self.config);
        self
    }

    pub fn with_publish_rate_limit(self, rate: Duration, burst: i32) -> Self {
        self.with_config(|config| {
            config.publish_rate_limit.rate = rate;
            config.publish_rate_limit.burst = burst;
        })
    }

    pub fn with_git_index(mut self) -> Self {
        self.index = Some(UpstreamIndex::new().unwrap());
        self
    }

    pub fn with_job_runner(mut self) -> Self {
        self.build_job_runner = true;
        self
    }

    /// Configures the test database
    pub fn with_database(mut self, test_database: TestDatabase) -> Self {
        self.config.use_test_database_pool = false;
        self.test_database = test_database;
        self
    }
}

pub fn init_logger() {
    let _ = tracing_subscriber::fmt()
        .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
        .without_time()
        .with_test_writer()
        .try_init();
}

fn simple_config() -> config::Server {
    config::Server {
        base: config::Base::test(),
        db: config::DatabasePools::test_from_environment(),
        session_key: "test this has to be over 32 bytes long".to_string(),
        gh_client_id: dotenv::var("GH_CLIENT_ID").unwrap_or_default(),
        gh_client_secret: dotenv::var("GH_CLIENT_SECRET").unwrap_or_default(),
        gh_base_url: "http://api.github.com".to_string(),
        max_upload_size: 3000,
        max_unpack_size: 2000,
        publish_rate_limit: Default::default(),
        new_version_rate_limit: Some(10),
        blocked_traffic: Default::default(),
        max_allowed_page_offset: 200,
        page_offset_ua_blocklist: vec![],
        page_offset_cidr_blocklist: vec![],
        excluded_crate_names: vec![],
        domain_name: "crates.io".into(),
        allowed_origins: Vec::new(),
        downloads_persist_interval_ms: 1000,
        ownership_invitations_expiration_days: 30,
        metrics_authorization_token: None,
        use_test_database_pool: true,
        instance_metrics_log_every_seconds: None,
        force_unconditional_redirects: false,
        blocked_routes: HashSet::new(),
        version_id_cache_size: 10000,
        version_id_cache_ttl: Duration::from_secs(5 * 60),
    }
}

fn build_app(
    config: config::Server,
    proxy: Option<String>,
) -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    let client = if let Some(proxy) = proxy {
        let mut builder = Client::builder();
        builder = builder
            .proxy(Proxy::all(proxy).expect("Unable to configure proxy with the provided URL"));
        Some(builder.build().expect("TLS backend cannot be initialized"))
    } else {
        None
    };

    let mut app = App::new(config, client);

    // Use the in-memory email backend for all tests, allowing tests to analyze the emails sent by
    // the application. This will also prevent cluttering the filesystem.
    app.emails = Emails::new_in_memory();

    // Use a custom mock for the GitHub client, allowing to define the GitHub users and
    // organizations without actually having to create GitHub accounts.
    app.github = Box::new(MockGitHubClient::new(&MOCK_GITHUB_DATA));

    let app = Arc::new(app);
    let handler = cargo_registry::build_handler(Arc::clone(&app));
    (app, handler)
}
<commit_msg>tests: Automatically log everything with `INFO` level or above<commit_after>use super::{MockAnonymousUser, MockCookieUser, MockTokenUser};
use crate::record;
use crate::util::{chaosproxy::ChaosProxy, fresh_schema::FreshSchema};
use cargo_registry::config::{self, DbPoolConfig};
use cargo_registry::{background_jobs::Environment, db::DieselPool, App, Emails};
use cargo_registry_index::testing::UpstreamIndex;
use cargo_registry_index::{Credentials, Repository as WorkerRepository, RepositoryConfig};
use std::{rc::Rc, sync::Arc, time::Duration};

use crate::util::github::{MockGitHubClient, MOCK_GITHUB_DATA};
use diesel::PgConnection;
use reqwest::{blocking::Client, Proxy};
use std::collections::HashSet;
use swirl::Runner;

struct TestAppInner {
    app: Arc<App>,
    // The bomb (if created) needs to be held in scope until the end of the test.
    _bomb: Option<record::Bomb>,
    middle: conduit_middleware::MiddlewareBuilder,
    index: Option<UpstreamIndex>,
    runner: Option<Runner<Environment, DieselPool>>,

    primary_db_chaosproxy: Option<Arc<ChaosProxy>>,
    replica_db_chaosproxy: Option<Arc<ChaosProxy>>,

    // Must be the last field of the struct!
    _fresh_schema: Option<FreshSchema>,
}

impl Drop for TestAppInner {
    fn drop(&mut self) {
        use diesel::prelude::*;
        use swirl::schema::background_jobs::dsl::*;

        // Avoid a double-panic if the test is already failing
        if std::thread::panicking() {
            return;
        }

        // Lazily run any remaining jobs
        if let Some(runner) = &self.runner {
            runner.run_all_pending_jobs().expect("Could not run jobs");
            runner.check_for_failed_jobs().expect("Failed jobs remain");
        }

        // Manually verify that all jobs have completed successfully
        // This will catch any tests that enqueued a job but forgot to initialize the runner
        let conn = self.app.primary_database.get().unwrap();
        let job_count: i64 = background_jobs.count().get_result(&*conn).unwrap();
        assert_eq!(
            0, job_count,
            "Unprocessed or failed jobs remain in the queue"
        );

        // TODO: If a runner was started, obtain the clone from it and ensure its HEAD matches the upstream index HEAD
    }
}

/// A representation of the app and its database transaction
#[derive(Clone)]
pub struct TestApp(Rc<TestAppInner>);

impl TestApp {
    /// Initialize an application with an `Uploader` that panics
    pub fn init() -> TestAppBuilder {
        init_logger();

        TestAppBuilder {
            config: simple_config(),
            proxy: None,
            bomb: None,
            index: None,
            build_job_runner: false,
            test_database: TestDatabase::TestPool,
        }
    }

    /// Initialize the app and a proxy that can record and playback outgoing HTTP requests
    pub fn with_proxy() -> TestAppBuilder {
        Self::init().with_proxy()
    }

    /// Initialize a full application, with a proxy, index, and background worker
    pub fn full() -> TestAppBuilder {
        Self::with_proxy().with_git_index().with_job_runner()
    }

    /// Obtain the database connection and pass it to the closure
    ///
    /// Within each test, the connection pool only has 1 connection so it is necessary to drop the
    /// connection before making any API calls.  Once the closure returns, the connection is
    /// dropped, ensuring it is returned to the pool and available for any future API calls.
    pub fn db<T, F: FnOnce(&PgConnection) -> T>(&self, f: F) -> T {
        let conn = self.0.app.primary_database.get().unwrap();
        f(&conn)
    }

    /// Create a new user with a verified email address in the database and return a mock user
    /// session
    ///
    /// This method updates the database directly
    pub fn db_new_user(&self, username: &str) -> MockCookieUser {
        use cargo_registry::schema::emails;
        use diesel::prelude::*;

        let user = self.db(|conn| {
            let email = "something@example.com";

            let user = crate::new_user(username)
                .create_or_update(None, &self.0.app.emails, conn)
                .unwrap();
            diesel::insert_into(emails::table)
                .values((
                    emails::user_id.eq(user.id),
                    emails::email.eq(email),
                    emails::verified.eq(true),
                ))
                .execute(conn)
                .unwrap();
            user
        });
        MockCookieUser {
            app: self.clone(),
            user,
        }
    }

    /// Obtain a reference to the upstream repository ("the index")
    pub fn upstream_index(&self) -> &UpstreamIndex {
        assert_some!(self.0.index.as_ref())
    }

    /// Obtain a list of crates from the index HEAD
    pub fn crates_from_index_head(&self, crate_name: &str) -> Vec<cargo_registry_index::Crate> {
        self.upstream_index()
            .crates_from_index_head(crate_name)
            .unwrap()
    }

    #[track_caller]
    pub fn run_pending_background_jobs(&self) {
        let runner = &self.0.runner;
        let runner = runner.as_ref().expect("Index has not been initialized");

        runner.run_all_pending_jobs().expect("Could not run jobs");
        runner
            .check_for_failed_jobs()
            .expect("Could not determine if jobs failed");
    }

    /// Obtain a reference to the inner `App` value
    pub fn as_inner(&self) -> &App {
        &self.0.app
    }

    /// Obtain a reference to the inner middleware builder
    pub fn as_middleware(&self) -> &conduit_middleware::MiddlewareBuilder {
        &self.0.middle
    }

    pub(crate) fn primary_db_chaosproxy(&self) -> Arc<ChaosProxy> {
        self.0
            .primary_db_chaosproxy
            .clone()
            .expect("ChaosProxy is not enabled on this test, call with_database during app init")
    }

    pub(crate) fn replica_db_chaosproxy(&self) -> Arc<ChaosProxy> {
        self.0
            .replica_db_chaosproxy
            .clone()
            .expect("ChaosProxy is not enabled on this test, call with_database during app init")
    }
}

/// Defines the type of test database.
pub enum TestDatabase {
    /// Use the fast test database pool
    TestPool,
    /// Use the slow test database pool with a fresh schema that enables ChaosProxy
    /// TODO rewrite comment, uses a database pool
    SlowRealPool { replica: bool },
}

pub struct TestAppBuilder {
    config: config::Server,
    proxy: Option<String>,
    bomb: Option<record::Bomb>,
    index: Option<UpstreamIndex>,
    build_job_runner: bool,
    test_database: TestDatabase,
}

impl TestAppBuilder {
    /// Create a `TestApp` with an empty database
    pub fn empty(mut self) -> (TestApp, MockAnonymousUser) {
        // Run each test inside a fresh database schema, deleted at the end of the test,
        // The schema will be cleared up once the app is dropped.
        let (primary_db_chaosproxy, replica_db_chaosproxy, fresh_schema) =
            if !self.config.use_test_database_pool {
                let fresh_schema = FreshSchema::new(&self.config.db.primary.url);
                let (primary_proxy, url) =
                    ChaosProxy::proxy_database_url(fresh_schema.database_url()).unwrap();
                self.config.db.primary.url = url;

                let replica_proxy = match self.test_database {
                    TestDatabase::SlowRealPool { replica: true } => {
                        let (replica_proxy, url) =
                            ChaosProxy::proxy_database_url(fresh_schema.database_url()).unwrap();
                        self.config.db.replica = Some(DbPoolConfig {
                            url,
                            read_only_mode: true,
                            pool_size: 1,
                            min_idle: None,
                        });
                        Some(replica_proxy)
                    }
                    _ => None,
                };

                (Some(primary_proxy), replica_proxy, Some(fresh_schema))
            } else {
                (None, None, None)
            };

        let (app, middle) = build_app(self.config, self.proxy);

        let runner = if self.build_job_runner {
            let repository_config = RepositoryConfig {
                index_location: UpstreamIndex::url(),
                credentials: Credentials::Missing,
            };
            let index = WorkerRepository::open(&repository_config).expect("Could not clone index");
            let environment = Environment::new(
                index,
                app.config.uploader().clone(),
                app.http_client().clone(),
                None,
            );

            Some(
                Runner::builder(environment)
                    // We only have 1 connection in tests, so trying to run more than
                    // 1 job concurrently will just block
                    .thread_count(1)
                    .connection_pool(app.primary_database.clone())
                    .job_start_timeout(Duration::from_secs(5))
                    .build(),
            )
        } else {
            None
        };

        let test_app_inner = TestAppInner {
            app,
            _fresh_schema: fresh_schema,
            _bomb: self.bomb,
            middle,
            index: self.index,
            runner,
            primary_db_chaosproxy,
            replica_db_chaosproxy,
        };
        let test_app = TestApp(Rc::new(test_app_inner));
        let anon = MockAnonymousUser {
            app: test_app.clone(),
        };
        (test_app, anon)
    }

    /// Create a proxy for use with this app
    pub fn with_proxy(mut self) -> Self {
        let (proxy, bomb) = record::proxy();
        self.proxy = Some(proxy);
        self.bomb = Some(bomb);
        self
    }

    // Create a `TestApp` with a database including a default user
    pub fn with_user(self) -> (TestApp, MockAnonymousUser, MockCookieUser) {
        let (app, anon) = self.empty();
        let user = app.db_new_user("foo");
        (app, anon, user)
    }

    /// Create a `TestApp` with a database including a default user and its token
    pub fn with_token(self) -> (TestApp, MockAnonymousUser, MockCookieUser, MockTokenUser) {
        let (app, anon) = self.empty();
        let user = app.db_new_user("foo");
        let token = user.db_new_token("bar");
        (app, anon, user, token)
    }

    pub fn with_config(mut self, f: impl FnOnce(&mut config::Server)) -> Self {
        f(&mut self.config);
        self
    }

    pub fn with_publish_rate_limit(self, rate: Duration, burst: i32) -> Self {
        self.with_config(|config| {
            config.publish_rate_limit.rate = rate;
            config.publish_rate_limit.burst = burst;
        })
    }

    pub fn with_git_index(mut self) -> Self {
        self.index = Some(UpstreamIndex::new().unwrap());
        self
    }

    pub fn with_job_runner(mut self) -> Self {
        self.build_job_runner = true;
        self
    }

    /// Configures the test database
    pub fn with_database(mut self, test_database: TestDatabase) -> Self {
        self.config.use_test_database_pool = false;
        self.test_database = test_database;
        self
    }
}

pub fn init_logger() {
    let _ = tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        .without_time()
        .with_test_writer()
        .try_init();
}

fn simple_config() -> config::Server {
    config::Server {
        base: config::Base::test(),
        db: config::DatabasePools::test_from_environment(),
        session_key: "test this has to be over 32 bytes long".to_string(),
        gh_client_id: dotenv::var("GH_CLIENT_ID").unwrap_or_default(),
        gh_client_secret: dotenv::var("GH_CLIENT_SECRET").unwrap_or_default(),
        gh_base_url: "http://api.github.com".to_string(),
        max_upload_size: 3000,
        max_unpack_size: 2000,
        publish_rate_limit: Default::default(),
        new_version_rate_limit: Some(10),
        blocked_traffic: Default::default(),
        max_allowed_page_offset: 200,
        page_offset_ua_blocklist: vec![],
        page_offset_cidr_blocklist: vec![],
        excluded_crate_names: vec![],
        domain_name: "crates.io".into(),
        allowed_origins: Vec::new(),
        downloads_persist_interval_ms: 1000,
        ownership_invitations_expiration_days: 30,
        metrics_authorization_token: None,
        use_test_database_pool: true,
        instance_metrics_log_every_seconds: None,
        force_unconditional_redirects: false,
        blocked_routes: HashSet::new(),
        version_id_cache_size: 10000,
        version_id_cache_ttl: Duration::from_secs(5 * 60),
    }
}

fn build_app(
    config: config::Server,
    proxy: Option<String>,
) -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    let client = if let Some(proxy) = proxy {
        let mut builder = Client::builder();
        builder = builder
            .proxy(Proxy::all(proxy).expect("Unable to configure proxy with the provided URL"));
        Some(builder.build().expect("TLS backend cannot be initialized"))
    } else {
        None
    };

    let mut app = App::new(config, client);

    // Use the in-memory email backend for all tests, allowing tests to analyze the emails sent by
    // the application. This will also prevent cluttering the filesystem.
    app.emails = Emails::new_in_memory();

    // Use a custom mock for the GitHub client, allowing to define the GitHub users and
    // organizations without actually having to create GitHub accounts.
    app.github = Box::new(MockGitHubClient::new(&MOCK_GITHUB_DATA));

    let app = Arc::new(app);
    let handler = cargo_registry::build_handler(Arc::clone(&app));
    (app, handler)
}
<|endoftext|>


<commit_before>//! Traits for abstracting away frame allocation and deallocation.

use crate::structures::paging::{PageSize, PhysFrame};

/// A trait for types that can allocate a frame of memory.
///
/// This trait is unsafe to implement because the implementer must guarantee that
/// the `allocate_frame` method returns only unique unused frames.
pub unsafe trait FrameAllocator<S: PageSize> {
    /// Allocate a frame of the appropriate size and return it if possible.
    fn allocate_frame(&mut self) -> Option<PhysFrame<S>>;
}

/// A trait for types that can deallocate a frame of memory.
pub trait FrameDeallocator<S: PageSize> {
    /// Deallocate the given unused frame.
    ///
    /// ## Safety
    ///
    /// The caller must ensure that the passed frame is unused.
    unsafe fn deallocate_frame(&mut self, frame: PhysFrame<S>);
}
<commit_msg>Add Safety comment to FrameAllocator<commit_after>//! Traits for abstracting away frame allocation and deallocation.

use crate::structures::paging::{PageSize, PhysFrame};

/// A trait for types that can allocate a frame of memory.
///
/// # Safety
///
/// The implementer of this trait must guarantee that the `allocate_frame`
/// method returns only unique unused frames. Otherwise, undefined behavior
/// may result from two caller modifying or deallocating the same frame.
pub unsafe trait FrameAllocator<S: PageSize> {
    /// Allocate a frame of the appropriate size and return it if possible.
    fn allocate_frame(&mut self) -> Option<PhysFrame<S>>;
}

/// A trait for types that can deallocate a frame of memory.
pub trait FrameDeallocator<S: PageSize> {
    /// Deallocate the given unused frame.
    ///
    /// ## Safety
    ///
    /// The caller must ensure that the passed frame is unused.
    unsafe fn deallocate_frame(&mut self, frame: PhysFrame<S>);
}
<|endoftext|>


<commit_before>use gtk::{WidgetExt, DrawingArea};
use cassowary;
use cassowary::math::variables::{new_var, new_const};
use cassowary::math::relationships::Relationship;
use cassowary::math::expressions::Expression;
use cassowary::objective::functions::Function;
use cassowary::objective::problems::ProblemType;
use cassowary::objective::constraints::{new_reg_con, SystemOfConstraints};
use pen::PenStream;
use visualiser::DrawCommand;

pub fn cal_demo1(da_width: f32, da_height: f32, pen: &mut PenStream) {
    let x_loc = 30.0;
    let y_loc = 20.0;
    let side_margin = 30.0;
    let top_margin = 20.0;
    let exp1 = Expression::new(vec![new_var("P", 1.0)],
                               Relationship::EQ,
                               vec![new_var("width", 1.0), new_var("height", 1.0)]);
    let exp2 = Expression::new(vec![new_var("width", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con1", da_width - 2.0 * side_margin)]);
    let exp3 = Expression::new(vec![new_var("height", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con2", da_height - 2.0 * top_margin)]);
    let mut objective_func = Function::new(exp1, ProblemType::MAX);
    let c1 = new_reg_con(exp2);
    let c2 = new_reg_con(exp3);
    let subject_to = SystemOfConstraints::new(vec![c1, c2]);
    let solution = cassowary::optimise(&mut objective_func, &subject_to);
    let width = solution.iter()
        .find(|&entry| entry.0 == "width")
        .unwrap()
        .1;
    let height = solution.iter()
        .find(|&entry| entry.0 == "height")
        .unwrap()
        .1;
    pen.add_rec_to_draw(x_loc as f64, y_loc as f64, width as f64, height as f64);
}

pub fn cal_demo2(x_loc1: f32,
                 y_loc1: f32,
                 x_loc2: f32,
                 y_loc2: f32,
                 side_margin: f32,
                 mid_margin: f32,
                 top_margin: f32,
                 da_width: f32,
                 da_height: f32,
                 pen: &mut PenStream) {
    let exp1 = Expression::new(vec![new_var("P", 1.0)],
                               Relationship::EQ,
                               vec![new_var("width1", 0.5),
                                    new_var("height1", 1.0),
                                    new_var("width2", 1.0),
                                    new_var("height2", 1.0)]);
    let exp2 = Expression::new(vec![new_var("width1", 1.0), new_var("width2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con1",
                                              da_width - (2.0 * side_margin) - mid_margin)]);
    let exp3 = Expression::new(vec![new_var("height1", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con2", da_height - 2.0 * top_margin)]);
    let exp4 = Expression::new(vec![new_var("height2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con3", da_height - 2.0 * top_margin)]);
    let exp5 = Expression::new(vec![new_var("width1", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con4", x_loc2 - x_loc1 - mid_margin)]);
    let exp6 = Expression::new(vec![new_var("width2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con4", da_width - (x_loc2 + side_margin))]);
    let mut objective_func = Function::new(exp1, ProblemType::MAX);
    let c1 = new_reg_con(exp2);
    let c2 = new_reg_con(exp3);
    let c3 = new_reg_con(exp4);
    let c4 = new_reg_con(exp5);
    let c5 = new_reg_con(exp6);
    let subject_to = SystemOfConstraints::new(vec![c1, c2, c3, c4, c5]);
    let solution = cassowary::optimise(&mut objective_func, &subject_to);
    let width1 = solution.iter()
        .find(|&entry| entry.0 == "width1")
        .unwrap()
        .1;
    let height1 = solution.iter()
        .find(|&entry| entry.0 == "height1")
        .unwrap()
        .1;
    let width2 = solution.iter()
        .find(|&entry| entry.0 == "width2")
        .unwrap()
        .1;
    let height2 = solution.iter()
        .find(|&entry| entry.0 == "height2")
        .unwrap()
        .1;
    pen.add_rec_to_draw(x_loc1 as f64, y_loc1 as f64, width1 as f64, height1 as f64);
    pen.add_rec_to_draw(x_loc2 as f64, y_loc2 as f64, width2 as f64, height2 as f64);
}

pub fn demo2_key_release(left: bool,
                         ri: usize,
                         pen: &mut PenStream,
                         da: &DrawingArea,
                         cs: &mut Vec<DrawCommand>) {
    let (x, y) = match left {
        true => {
            let rec_info = pen.rectangle_info(ri);
            (rec_info.0 - 5, rec_info.1)
        }
        false => {
            let rec_info = pen.rectangle_info(ri);
            (rec_info.0 + 5, rec_info.1)
        }
    };

    match ri {
        0 => {
            let (da_width, da_height) = drawing_area_height_width(da);
            let (x2, y2, _, _) = pen.rectangle_info(1);
            pen.clear_all_recs();
            cal_demo2(x as f32,
                      y as f32,
                      x2 as f32,
                      y2 as f32,
                      30.0,
                      20.0,
                      20.0,
                      da_width as f32,
                      da_height as f32,
                      pen);
            draw_demo2_key_release(x - 5, y, da_width, da_height, da, cs);
        }
        _ => {
            let (da_width, da_height) = drawing_area_height_width(da);
            let (x1, y1, _, _) = pen.rectangle_info(0);
            pen.clear_all_recs();
            cal_demo2(x1 as f32,
                      y1 as f32,
                      x as f32,
                      y as f32,
                      30.0,
                      20.0,
                      20.0,
                      da_width as f32,
                      da_height as f32,
                      pen);
            draw_demo2_key_release(x1, y1, da_width, da_height, da, cs);
        }
    }
}

pub fn cal_demo3(x_loc1: f32,
                 y_loc1: f32,
                 x_loc2: f32,
                 y_loc2: f32,
                 x_loc3: f32,
                 y_loc3: f32,
                 side_margin: f32,
                 mid_margin: f32,
                 top_margin: f32,
                 da_width: f32,
                 da_height: f32,
                 pen: &mut PenStream) {
    let exp1 = Expression::new(vec![new_var("P", 1.0)],
                               Relationship::EQ,
                               vec![new_var("width1", 1.0),
                                    new_var("height1", 1.0),
                                    new_var("width2", 1.0),
                                    new_var("height2", 1.0),
                                    new_var("width3", 1.0),
                                    new_var("height3", 1.0)]);
    let exp2 = Expression::new(vec![new_var("width2", 1.0), new_var("width3", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con1",
                                              da_width - (2.0 * side_margin) - (2.0 * mid_margin) -
                                              100.0)]);
    let exp3 = Expression::new(vec![new_var("height2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con2", da_height - (2.0 * top_margin))]);
    let exp4 = Expression::new(vec![new_var("height3", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con3", da_height - (2.0 * top_margin))]);
    let exp5 = Expression::new(vec![new_var("height1", 1.0)],
                               Relationship::EQ,
                               vec![new_const("con4", 100.0)]);
    let exp6 = Expression::new(vec![new_var("width2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con5", x_loc3 - x_loc2 - mid_margin)]);
    let exp7 = Expression::new(vec![new_var("width3", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con6", da_width - (x_loc3 + side_margin))]);
    let exp8 = Expression::new(vec![new_var("width1", 1.0)],
                               Relationship::EQ,
                               vec![new_const("con7", 100.0)]);
    let mut objective_func = Function::new(exp1, ProblemType::MAX);
    let c1 = new_reg_con(exp2);
    let c2 = new_reg_con(exp3);
    let c3 = new_reg_con(exp4);
    let c4 = new_reg_con(exp5);
    let c5 = new_reg_con(exp6);
    let c6 = new_reg_con(exp7);
    let c7 = new_reg_con(exp8);
    let subject_to = SystemOfConstraints::new(vec![c1, c2, c3, c4, c5, c6, c7]);
    let solution = cassowary::optimise(&mut objective_func, &subject_to);
    let width1 = solution.iter()
        .find(|&entry| entry.0 == "width1")
        .unwrap()
        .1;
    let height1 = solution.iter()
        .find(|&entry| entry.0 == "height1")
        .unwrap()
        .1;
    let width2 = solution.iter()
        .find(|&entry| entry.0 == "width2")
        .unwrap()
        .1;
    let height2 = solution.iter()
        .find(|&entry| entry.0 == "height2")
        .unwrap()
        .1;
    let width3 = solution.iter()
        .find(|&entry| entry.0 == "width3")
        .unwrap()
        .1;
    let height3 = solution.iter()
        .find(|&entry| entry.0 == "height3")
        .unwrap()
        .1;
    pen.add_rec_to_draw(x_loc1 as f64, y_loc1 as f64, width1 as f64, height1 as f64);
    pen.add_rec_to_draw(x_loc2 as f64, y_loc2 as f64, width2 as f64, height2 as f64);
    pen.add_rec_to_draw(x_loc3 as f64, y_loc3 as f64, width3 as f64, height3 as f64);
}

pub fn demo3_size_change(pen: &mut PenStream, da: &DrawingArea, cs: &mut Vec<DrawCommand>) {
    pen.clear_all_recs();
    let (da_width, da_height) = drawing_area_height_width(da);
    cal_demo3(30.0,
              20.0,
              150.0,
              20.0,
              300.0,
              20.0,
              30.0,
              20.0,
              20.0,
              da_width as f32,
              da_height as f32,
              pen);
    cs.push(DrawCommand::DrawAll);
    da.queue_draw_area(149, 19, da_width - 148, da_height - 38);
}

fn draw_demo2_key_release(x: i32,
                          y: i32,
                          da_w: i32,
                          da_h: i32,
                          da: &DrawingArea,
                          cs: &mut Vec<DrawCommand>) {
    cs.push(DrawCommand::DrawAll);
    da.queue_draw_area(x - 1, y - 1, da_w - 58, da_h - 38);
}

fn drawing_area_height_width(da: &DrawingArea) -> (i32, i32) {
    (da.get_allocated_width(), da.get_allocated_height())
}
<commit_msg>Remove explicit size of rectangle in total width constraint.<commit_after>use gtk::{WidgetExt, DrawingArea};
use cassowary;
use cassowary::math::variables::{new_var, new_const};
use cassowary::math::relationships::Relationship;
use cassowary::math::expressions::Expression;
use cassowary::objective::functions::Function;
use cassowary::objective::problems::ProblemType;
use cassowary::objective::constraints::{new_reg_con, SystemOfConstraints};
use pen::PenStream;
use visualiser::DrawCommand;

pub fn cal_demo1(da_width: f32, da_height: f32, pen: &mut PenStream) {
    let x_loc = 30.0;
    let y_loc = 20.0;
    let side_margin = 30.0;
    let top_margin = 20.0;
    let exp1 = Expression::new(vec![new_var("P", 1.0)],
                               Relationship::EQ,
                               vec![new_var("width", 1.0), new_var("height", 1.0)]);
    let exp2 = Expression::new(vec![new_var("width", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con1", da_width - 2.0 * side_margin)]);
    let exp3 = Expression::new(vec![new_var("height", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con2", da_height - 2.0 * top_margin)]);
    let mut objective_func = Function::new(exp1, ProblemType::MAX);
    let c1 = new_reg_con(exp2);
    let c2 = new_reg_con(exp3);
    let subject_to = SystemOfConstraints::new(vec![c1, c2]);
    let solution = cassowary::optimise(&mut objective_func, &subject_to);
    let width = solution.iter()
        .find(|&entry| entry.0 == "width")
        .unwrap()
        .1;
    let height = solution.iter()
        .find(|&entry| entry.0 == "height")
        .unwrap()
        .1;
    pen.add_rec_to_draw(x_loc as f64, y_loc as f64, width as f64, height as f64);
}

pub fn cal_demo2(x_loc1: f32,
                 y_loc1: f32,
                 x_loc2: f32,
                 y_loc2: f32,
                 side_margin: f32,
                 mid_margin: f32,
                 top_margin: f32,
                 da_width: f32,
                 da_height: f32,
                 pen: &mut PenStream) {
    let exp1 = Expression::new(vec![new_var("P", 1.0)],
                               Relationship::EQ,
                               vec![new_var("width1", 0.5),
                                    new_var("height1", 1.0),
                                    new_var("width2", 1.0),
                                    new_var("height2", 1.0)]);
    let exp2 = Expression::new(vec![new_var("width1", 1.0), new_var("width2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con1",
                                              da_width - (2.0 * side_margin) - mid_margin)]);
    let exp3 = Expression::new(vec![new_var("height1", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con2", da_height - 2.0 * top_margin)]);
    let exp4 = Expression::new(vec![new_var("height2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con3", da_height - 2.0 * top_margin)]);
    let exp5 = Expression::new(vec![new_var("width1", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con4", x_loc2 - x_loc1 - mid_margin)]);
    let exp6 = Expression::new(vec![new_var("width2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con4", da_width - (x_loc2 + side_margin))]);
    let mut objective_func = Function::new(exp1, ProblemType::MAX);
    let c1 = new_reg_con(exp2);
    let c2 = new_reg_con(exp3);
    let c3 = new_reg_con(exp4);
    let c4 = new_reg_con(exp5);
    let c5 = new_reg_con(exp6);
    let subject_to = SystemOfConstraints::new(vec![c1, c2, c3, c4, c5]);
    let solution = cassowary::optimise(&mut objective_func, &subject_to);
    let width1 = solution.iter()
        .find(|&entry| entry.0 == "width1")
        .unwrap()
        .1;
    let height1 = solution.iter()
        .find(|&entry| entry.0 == "height1")
        .unwrap()
        .1;
    let width2 = solution.iter()
        .find(|&entry| entry.0 == "width2")
        .unwrap()
        .1;
    let height2 = solution.iter()
        .find(|&entry| entry.0 == "height2")
        .unwrap()
        .1;
    pen.add_rec_to_draw(x_loc1 as f64, y_loc1 as f64, width1 as f64, height1 as f64);
    pen.add_rec_to_draw(x_loc2 as f64, y_loc2 as f64, width2 as f64, height2 as f64);
}

pub fn demo2_key_release(left: bool,
                         ri: usize,
                         pen: &mut PenStream,
                         da: &DrawingArea,
                         cs: &mut Vec<DrawCommand>) {
    let (x, y) = match left {
        true => {
            let rec_info = pen.rectangle_info(ri);
            (rec_info.0 - 5, rec_info.1)
        }
        false => {
            let rec_info = pen.rectangle_info(ri);
            (rec_info.0 + 5, rec_info.1)
        }
    };

    match ri {
        0 => {
            let (da_width, da_height) = drawing_area_height_width(da);
            let (x2, y2, _, _) = pen.rectangle_info(1);
            pen.clear_all_recs();
            cal_demo2(x as f32,
                      y as f32,
                      x2 as f32,
                      y2 as f32,
                      30.0,
                      20.0,
                      20.0,
                      da_width as f32,
                      da_height as f32,
                      pen);
            draw_demo2_key_release(x - 5, y, da_width, da_height, da, cs);
        }
        _ => {
            let (da_width, da_height) = drawing_area_height_width(da);
            let (x1, y1, _, _) = pen.rectangle_info(0);
            pen.clear_all_recs();
            cal_demo2(x1 as f32,
                      y1 as f32,
                      x as f32,
                      y as f32,
                      30.0,
                      20.0,
                      20.0,
                      da_width as f32,
                      da_height as f32,
                      pen);
            draw_demo2_key_release(x1, y1, da_width, da_height, da, cs);
        }
    }
}

pub fn cal_demo3(x_loc1: f32,
                 y_loc1: f32,
                 x_loc2: f32,
                 y_loc2: f32,
                 x_loc3: f32,
                 y_loc3: f32,
                 side_margin: f32,
                 mid_margin: f32,
                 top_margin: f32,
                 da_width: f32,
                 da_height: f32,
                 pen: &mut PenStream) {
    let exp1 = Expression::new(vec![new_var("P", 1.0)],
                               Relationship::EQ,
                               vec![new_var("width1", 1.0),
                                    new_var("height1", 1.0),
                                    new_var("width2", 1.0),
                                    new_var("height2", 1.0),
                                    new_var("width3", 1.0),
                                    new_var("height3", 1.0)]);
    let exp2 = Expression::new(vec![new_var("width1", 1.0),
                                    new_var("width2", 1.0),
                                    new_var("width3", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con1",
                                              da_width - (2.0 * side_margin) -
                                              (2.0 * mid_margin))]);
    let exp3 = Expression::new(vec![new_var("height2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con2", da_height - (2.0 * top_margin))]);
    let exp4 = Expression::new(vec![new_var("height3", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con3", da_height - (2.0 * top_margin))]);
    let exp5 = Expression::new(vec![new_var("height1", 1.0)],
                               Relationship::EQ,
                               vec![new_const("con4", 100.0)]);
    let exp6 = Expression::new(vec![new_var("width2", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con5", x_loc3 - x_loc2 - mid_margin)]);
    let exp7 = Expression::new(vec![new_var("width3", 1.0)],
                               Relationship::LEQ,
                               vec![new_const("con6", da_width - (x_loc3 + side_margin))]);
    let exp8 = Expression::new(vec![new_var("width1", 1.0)],
                               Relationship::EQ,
                               vec![new_const("con7", 100.0)]);
    let mut objective_func = Function::new(exp1, ProblemType::MAX);
    let c1 = new_reg_con(exp2);
    let c2 = new_reg_con(exp3);
    let c3 = new_reg_con(exp4);
    let c4 = new_reg_con(exp5);
    let c5 = new_reg_con(exp6);
    let c6 = new_reg_con(exp7);
    let c7 = new_reg_con(exp8);
    let subject_to = SystemOfConstraints::new(vec![c1, c2, c3, c4, c5, c6, c7]);
    let solution = cassowary::optimise(&mut objective_func, &subject_to);
    let width1 = solution.iter()
        .find(|&entry| entry.0 == "width1")
        .unwrap()
        .1;
    let height1 = solution.iter()
        .find(|&entry| entry.0 == "height1")
        .unwrap()
        .1;
    let width2 = solution.iter()
        .find(|&entry| entry.0 == "width2")
        .unwrap()
        .1;
    let height2 = solution.iter()
        .find(|&entry| entry.0 == "height2")
        .unwrap()
        .1;
    let width3 = solution.iter()
        .find(|&entry| entry.0 == "width3")
        .unwrap()
        .1;
    let height3 = solution.iter()
        .find(|&entry| entry.0 == "height3")
        .unwrap()
        .1;
    pen.add_rec_to_draw(x_loc1 as f64, y_loc1 as f64, width1 as f64, height1 as f64);
    pen.add_rec_to_draw(x_loc2 as f64, y_loc2 as f64, width2 as f64, height2 as f64);
    pen.add_rec_to_draw(x_loc3 as f64, y_loc3 as f64, width3 as f64, height3 as f64);
}

pub fn demo3_size_change(pen: &mut PenStream, da: &DrawingArea, cs: &mut Vec<DrawCommand>) {
    pen.clear_all_recs();
    let (da_width, da_height) = drawing_area_height_width(da);
    cal_demo3(30.0,
              20.0,
              150.0,
              20.0,
              300.0,
              20.0,
              30.0,
              20.0,
              20.0,
              da_width as f32,
              da_height as f32,
              pen);
    cs.push(DrawCommand::DrawAll);
    da.queue_draw_area(149, 19, da_width - 148, da_height - 38);
}

fn draw_demo2_key_release(x: i32,
                          y: i32,
                          da_w: i32,
                          da_h: i32,
                          da: &DrawingArea,
                          cs: &mut Vec<DrawCommand>) {
    cs.push(DrawCommand::DrawAll);
    da.queue_draw_area(x - 1, y - 1, da_w - 58, da_h - 38);
}

fn drawing_area_height_width(da: &DrawingArea) -> (i32, i32) {
    (da.get_allocated_width(), da.get_allocated_height())
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::os::unix::fs::symlink;
use std::os::unix::prelude::AsRawFd;

use libc::{S_IFMT, S_IFLNK};

use nix::fcntl;
use nix::sys::stat::{self, stat, fstat, lstat};
use nix::sys::stat::FileStat;
use nix::Result;
use tempdir::TempDir;

#[allow(unused_comparisons)]
// uid and gid are signed on Windows, but not on other platforms. This function
// allows warning free compiles on all platforms, and can be removed when
// expression-level #[allow] is available.
fn valid_uid_gid(stat: FileStat) -> bool {
    // uid could be 0 for the `root` user. This quite possible when
    // the tests are being run on a rooted Android device.
    stat.st_uid >= 0 && stat.st_gid >= 0
}

fn assert_stat_results(stat_result: Result<FileStat>) {
    match stat_result {
        Ok(stats) => {
            assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
            assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
            assert!(stats.st_mode > 0);     // must be positive integer
            assert!(stats.st_nlink == 1);   // there links created, must be 1
            assert!(valid_uid_gid(stats));  // must be positive integers
            assert!(stats.st_size == 0);    // size is 0 because we did not write anything to the file
            assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
            assert!(stats.st_blocks <= 16);  // Up to 16 blocks can be allocated for a blank file
        }
        Err(_) => panic!("stat call failed") // if stats system call fails, something is seriously wrong on that machine
    }
}

fn assert_lstat_results(stat_result: Result<FileStat>) {
    match stat_result {
        Ok(stats) => {
            assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
            assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
            assert!(stats.st_mode > 0);     // must be positive integer

            // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
            // (u16 on Android), and that will be a compile error.
            // On other platforms they are the same (either both are u16 or u32).
            assert!((stats.st_mode as usize) & (S_IFMT as usize) == S_IFLNK as usize); // should be a link
            assert!(stats.st_nlink == 1);   // there links created, must be 1
            assert!(valid_uid_gid(stats));  // must be positive integers
            assert!(stats.st_size > 0);    // size is > 0 because it points to another file
            assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent

            // st_blocks depends on whether the machine's file system uses fast
            // or slow symlinks, so just make sure it's not negative
            // (Android's st_blocks is ulonglong which is always non-negative.)
            assert!(stats.st_blocks >= 0);
        }
        Err(_) => panic!("stat call failed") // if stats system call fails, something is seriously wrong on that machine
    }
}

#[test]
fn test_stat_and_fstat() {
    let tempdir = TempDir::new("nix-test_stat_and_fstat").unwrap();
    let filename = tempdir.path().join("foo.txt");
    let file = File::create(&filename).unwrap();

    let stat_result = stat(&filename);
    assert_stat_results(stat_result);

    let fstat_result = fstat(file.as_raw_fd());
    assert_stat_results(fstat_result);
}

#[test]
fn test_fstatat() {
    let tempdir = TempDir::new("nix-test_stat_and_fstat").unwrap();
    let filename = tempdir.path().join("foo.txt");
    File::create(&filename).unwrap();
    let dirfd = fcntl::open(tempdir.path(),
                            fcntl::OFlag::empty(),
                            stat::Mode::empty());

    let result = stat::fstatat(dirfd.unwrap(),
                               &filename,
                               fcntl::AtFlags::empty());
    assert_stat_results(result);
}

#[test]
fn test_stat_fstat_lstat() {
    let tempdir = TempDir::new("nix-test_stat_fstat_lstat").unwrap();
    let filename = tempdir.path().join("bar.txt");
    let linkname = tempdir.path().join("barlink");

    File::create(&filename).unwrap();
    symlink("bar.txt", &linkname).unwrap();
    let link = File::open(&linkname).unwrap();

    // should be the same result as calling stat,
    // since it's a regular file
    let stat_result = lstat(&filename);
    assert_stat_results(stat_result);

    let lstat_result = lstat(&linkname);
    assert_lstat_results(lstat_result);

    let fstat_result = fstat(link.as_raw_fd());
    assert_stat_results(fstat_result);
}
<commit_msg>test/test_stat.rs: test correct stat function<commit_after>use std::fs::File;
use std::os::unix::fs::symlink;
use std::os::unix::prelude::AsRawFd;

use libc::{S_IFMT, S_IFLNK};

use nix::fcntl;
use nix::sys::stat::{self, stat, fstat, lstat};
use nix::sys::stat::FileStat;
use nix::Result;
use tempdir::TempDir;

#[allow(unused_comparisons)]
// uid and gid are signed on Windows, but not on other platforms. This function
// allows warning free compiles on all platforms, and can be removed when
// expression-level #[allow] is available.
fn valid_uid_gid(stat: FileStat) -> bool {
    // uid could be 0 for the `root` user. This quite possible when
    // the tests are being run on a rooted Android device.
    stat.st_uid >= 0 && stat.st_gid >= 0
}

fn assert_stat_results(stat_result: Result<FileStat>) {
    match stat_result {
        Ok(stats) => {
            assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
            assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
            assert!(stats.st_mode > 0);     // must be positive integer
            assert!(stats.st_nlink == 1);   // there links created, must be 1
            assert!(valid_uid_gid(stats));  // must be positive integers
            assert!(stats.st_size == 0);    // size is 0 because we did not write anything to the file
            assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
            assert!(stats.st_blocks <= 16);  // Up to 16 blocks can be allocated for a blank file
        }
        Err(_) => panic!("stat call failed") // if stats system call fails, something is seriously wrong on that machine
    }
}

fn assert_lstat_results(stat_result: Result<FileStat>) {
    match stat_result {
        Ok(stats) => {
            assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
            assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
            assert!(stats.st_mode > 0);     // must be positive integer

            // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
            // (u16 on Android), and that will be a compile error.
            // On other platforms they are the same (either both are u16 or u32).
            assert!((stats.st_mode as usize) & (S_IFMT as usize) == S_IFLNK as usize); // should be a link
            assert!(stats.st_nlink == 1);   // there links created, must be 1
            assert!(valid_uid_gid(stats));  // must be positive integers
            assert!(stats.st_size > 0);    // size is > 0 because it points to another file
            assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent

            // st_blocks depends on whether the machine's file system uses fast
            // or slow symlinks, so just make sure it's not negative
            // (Android's st_blocks is ulonglong which is always non-negative.)
            assert!(stats.st_blocks >= 0);
        }
        Err(_) => panic!("stat call failed") // if stats system call fails, something is seriously wrong on that machine
    }
}

#[test]
fn test_stat_and_fstat() {
    let tempdir = TempDir::new("nix-test_stat_and_fstat").unwrap();
    let filename = tempdir.path().join("foo.txt");
    let file = File::create(&filename).unwrap();

    let stat_result = stat(&filename);
    assert_stat_results(stat_result);

    let fstat_result = fstat(file.as_raw_fd());
    assert_stat_results(fstat_result);
}

#[test]
fn test_fstatat() {
    let tempdir = TempDir::new("nix-test_stat_and_fstat").unwrap();
    let filename = tempdir.path().join("foo.txt");
    File::create(&filename).unwrap();
    let dirfd = fcntl::open(tempdir.path(),
                            fcntl::OFlag::empty(),
                            stat::Mode::empty());

    let result = stat::fstatat(dirfd.unwrap(),
                               &filename,
                               fcntl::AtFlags::empty());
    assert_stat_results(result);
}

#[test]
fn test_stat_fstat_lstat() {
    let tempdir = TempDir::new("nix-test_stat_fstat_lstat").unwrap();
    let filename = tempdir.path().join("bar.txt");
    let linkname = tempdir.path().join("barlink");

    File::create(&filename).unwrap();
    symlink("bar.txt", &linkname).unwrap();
    let link = File::open(&linkname).unwrap();

    // should be the same result as calling stat,
    // since it's a regular file
    let stat_result = stat(&filename);
    assert_stat_results(stat_result);

    let lstat_result = lstat(&linkname);
    assert_lstat_results(lstat_result);

    let fstat_result = fstat(link.as_raw_fd());
    assert_stat_results(fstat_result);
}
<|endoftext|>


<commit_before>// 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.

extern crate quickcheck;
extern crate hamt;
use quickcheck::{Arbitrary, Gen, quickcheck};
use std::collections::HashMap;
use hamt::HamtRc;

#[derive(Copy, Clone, Debug)]
enum Command {
    Insert(isize, isize),
    Remove(isize),
    CheckEquals(isize),
}

impl Arbitrary for Command {
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        let cmd: usize = Arbitrary::arbitrary(g);
        let key: isize = Arbitrary::arbitrary(g);
        match cmd % 5 {
            0 => Command::CheckEquals(key % 200),
            1 => Command::Remove(key % 200),
            _ => {
                let value: isize = Arbitrary::arbitrary(g);
                Command::Insert(key % 200, value % 200)
            }
        }
    }
}

#[derive(Clone, Debug)]
struct Commands {
    cmds: Vec<Command>,
}

impl Arbitrary for Commands {
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        let mut cmds = Vec::new();
        for _ in 0..50000 {
            cmds.push(Arbitrary::arbitrary(g));
        }
        return Commands { cmds: cmds };
    }
}

fn simulation_testing(v: Commands) -> bool {
    let mut hamt: HamtRc<isize, isize> = HamtRc::new();
    let mut hashmap: HashMap<isize, isize> = HashMap::new();
    for cmd in v.cmds {
        match cmd {
            Command::Insert(k, v) => {
                hamt = hamt.insert(&k, &v);
                hashmap.insert(k, v);

                if hamt.contains_key(&k) != hashmap.contains_key(&k) {
                    return false;
                }
            }
            Command::Remove(k) => {
                hamt = hamt.remove(&k);
                hashmap.remove(&k);

                if hamt.contains_key(&k) != hashmap.contains_key(&k) {
                    return false;
                }
            }
            Command::CheckEquals(k) => {
                if hamt.get(&k) != hashmap.get(&k) {
                    return false;
                }
            }
        }
        if hamt.len() != hashmap.len() {
            return false;
        }
    }

    for (key, val) in &hashmap {
        if &hamt[key] != val {
            return false;
        }
    }

    for (key, val) in &hamt {
        if &hashmap[key] != val {
            return false;
        }
    }
    return true;
}

#[test]
fn test_simulation_testing() {
    quickcheck(simulation_testing as fn(Commands) -> bool);
}
<commit_msg>just changing some constants to reflect the 50,000 iterations<commit_after>// 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.

extern crate quickcheck;
extern crate hamt;
use quickcheck::{Arbitrary, Gen, quickcheck};
use std::collections::HashMap;
use hamt::HamtRc;

#[derive(Copy, Clone, Debug)]
enum Command {
    Insert(isize, isize),
    Remove(isize),
    CheckEquals(isize),
}

impl Arbitrary for Command {
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        let cmd: usize = Arbitrary::arbitrary(g);
        let key: isize = Arbitrary::arbitrary(g);
        match cmd % 5 {
            0 => Command::CheckEquals(key % 1000),
            1 => Command::Remove(key % 1000),
            _ => {
                let value: isize = Arbitrary::arbitrary(g);
                Command::Insert(key % 1000, value % 1000)
            }
        }
    }
}

#[derive(Clone, Debug)]
struct Commands {
    cmds: Vec<Command>,
}

impl Arbitrary for Commands {
    fn arbitrary<G: Gen>(g: &mut G) -> Self {
        let mut cmds = Vec::new();
        for _ in 0..50000 {
            cmds.push(Arbitrary::arbitrary(g));
        }
        return Commands { cmds: cmds };
    }
}

fn simulation_testing(v: Commands) -> bool {
    let mut hamt: HamtRc<isize, isize> = HamtRc::new();
    let mut hashmap: HashMap<isize, isize> = HashMap::new();
    for cmd in v.cmds {
        match cmd {
            Command::Insert(k, v) => {
                hamt = hamt.insert(&k, &v);
                hashmap.insert(k, v);

                if hamt.contains_key(&k) != hashmap.contains_key(&k) {
                    return false;
                }
            }
            Command::Remove(k) => {
                hamt = hamt.remove(&k);
                hashmap.remove(&k);

                if hamt.contains_key(&k) != hashmap.contains_key(&k) {
                    return false;
                }
            }
            Command::CheckEquals(k) => {
                if hamt.get(&k) != hashmap.get(&k) {
                    return false;
                }
            }
        }
        if hamt.len() != hashmap.len() {
            return false;
        }
    }

    for (key, val) in &hashmap {
        if &hamt[key] != val {
            return false;
        }
    }

    for (key, val) in &hamt {
        if &hashmap[key] != val {
            return false;
        }
    }
    return true;
}

#[test]
fn test_simulation_testing() {
    quickcheck(simulation_testing as fn(Commands) -> bool);
}
<|endoftext|>


<commit_before>use gilrs;
use gilrs::Gilrs;
use gilrs::ev::filter::{Filter, Repeat};

use frontend::input;
use frontend::input::EventMapper;

pub struct GamepadEventLoop {
	repeat_filter: Repeat,
	gilrs: Gilrs,
}

impl input::EventMapper<gilrs::Event> for GamepadEventLoop {
	fn translate(&self, _e: &gilrs::Event) -> Option<input::Event> {
		None
	}
}

impl GamepadEventLoop {
	pub fn new() -> Self {
		GamepadEventLoop {
			repeat_filter: Repeat::new(),
			gilrs: Gilrs::new(),
		}
	}

	pub fn poll_events<F>(&mut self, mut on_input_event: F)
		where F: FnMut(input::Event) {
		let repeat_filter = self.repeat_filter.clone();
		while let Some(ev) = Filter::filter(&self.gilrs.next_event(), &repeat_filter, &self.gilrs) {
			self.gilrs.update(&ev);
			println!("{:?}", ev);
			self.translate(&ev).map(&mut on_input_event);
		};
		self.gilrs.inc();
	}
}
<commit_msg>Removed repeat filtering for gamepad button pressed<commit_after>use gilrs;
use gilrs::Gilrs;
// use gilrs::ev::filter::{Filter, Repeat};

use frontend::input;
use frontend::input::EventMapper;

pub struct GamepadEventLoop {
	//	repeat_filter: Repeat,
	gilrs: Gilrs,
}

impl input::EventMapper<gilrs::Event> for GamepadEventLoop {
	fn translate(&self, _e: &gilrs::Event) -> Option<input::Event> {
		None
	}
}

impl GamepadEventLoop {
	pub fn new() -> Self {
		let gilrs = Gilrs::new();
		for (_id, gamepad) in gilrs.gamepads() {
			println!("{} is {:?}", gamepad.name(), gamepad.power_info());
		}
		GamepadEventLoop {
//			repeat_filter: Repeat::new(),
			gilrs,
		}
	}

	pub fn poll_events<F>(&mut self, mut on_input_event: F)
		where F: FnMut(input::Event) {
		//let repeat_filter = self.repeat_filter.clone();
		//while let Some(ev) = Filter::filter(&self.gilrs.next_event(), &repeat_filter, &self.gilrs) {
		while let Some(ev) = self.gilrs.next_event() {
			self.gilrs.update(&ev);
			println!("{:?}", ev);
			self.translate(&ev).map(&mut on_input_event);
		};
		self.gilrs.inc();
	}
}
<|endoftext|>


<commit_before>extern crate tempfile;
use std::io::{Read, Seek, SeekFrom, Write};
use std::fs;

#[test]
fn test_basic() {
    let mut tmpfile = tempfile::tempfile().unwrap();
    write!(tmpfile, "abcde").unwrap();
    tmpfile.seek(SeekFrom::Start(0)).unwrap();
    let mut buf = String::new();
    tmpfile.read_to_string(&mut buf).unwrap();
    assert_eq!("abcde", buf);
}

#[test]
fn test_cleanup() {
    let tmpdir = tempfile::tempdir().unwrap();
    {
        let mut tmpfile = tempfile::tempfile_in(&tmpdir).unwrap();
        write!(tmpfile, "abcde").unwrap();
    }
    let num_files = fs::read_dir(&tmpdir).unwrap().count();
    assert!(num_files == 0);
}
<commit_msg>Add test to emulate a pathological temporary file cleaner<commit_after>extern crate tempfile;
use std::io::{Read, Seek, SeekFrom, Write};
use std::fs;
use std::thread;
use std::sync::mpsc::{sync_channel, TryRecvError};

#[test]
fn test_basic() {
    let mut tmpfile = tempfile::tempfile().unwrap();
    write!(tmpfile, "abcde").unwrap();
    tmpfile.seek(SeekFrom::Start(0)).unwrap();
    let mut buf = String::new();
    tmpfile.read_to_string(&mut buf).unwrap();
    assert_eq!("abcde", buf);
}

#[test]
fn test_cleanup() {
    let tmpdir = tempfile::tempdir().unwrap();
    {
        let mut tmpfile = tempfile::tempfile_in(&tmpdir).unwrap();
        write!(tmpfile, "abcde").unwrap();
    }
    let num_files = fs::read_dir(&tmpdir).unwrap().count();
    assert!(num_files == 0);
}

#[test]
fn test_pathological_cleaner() {
    let tmpdir = tempfile::tempdir().unwrap();
    let (tx, rx) = sync_channel(0);
    let cleaner_thread = thread::spawn(move || {
        let tmp_path = rx.recv().unwrap();
        while rx.try_recv() == Err(TryRecvError::Empty) {
            let files = fs::read_dir(&tmp_path).unwrap();
            for f in files {
                // skip errors
                if f.is_err() {
                    continue;
                }
                let f = f.unwrap();
                let _ = fs::remove_file(f.path());
            }
        }
    });

    // block until cleaner_thread makes progress
    tx.send(tmpdir.path().to_owned()).unwrap();
    // need 40-400 iterations to encounter race with cleaner on original system
    for _ in 0..10000 {
        let mut tmpfile = tempfile::tempfile_in(&tmpdir).unwrap();
        write!(tmpfile, "abcde").unwrap();
        tmpfile.seek(SeekFrom::Start(0)).unwrap();
        let mut buf = String::new();
        tmpfile.read_to_string(&mut buf).unwrap();
        assert_eq!("abcde", buf);
    }

    // close the channel to make cleaner_thread exit
    drop(tx);
    cleaner_thread.join().expect("The cleaner thread failed");
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn chegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_complex, lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_real, bp: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublereal, bp: CLPK_doublereal,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_complex, bp: CLPK_complex,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublecomplex,
            bp: CLPK_doublecomplex, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn ssbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_real,
            ldab: CLPK_integer, bb: CLPK_real, ldbb: CLPK_integer,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_doublereal,
            ldab: CLPK_integer, bb: CLPK_doublereal, ldbb: CLPK_integer,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<commit_msg>Add Hbgv trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use libc::{
    c_char,
    c_int,
};

use types::{
    CLPK_complex,
    CLPK_doublecomplex,
    CLPK_doublereal,
    CLPK_integer,
    CLPK_real,
};

#[link(name = "lapack")]
extern "C" {
    pub fn ssygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_real, lda: *const CLPK_integer,
            b: *mut CLPK_real, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_real, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsygv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublereal, lda: *const CLPK_integer,
            b: *mut CLPK_doublereal, ldb: *const CLPK_integer, w: CLPK_doublereal,
            work: CLPK_doublereal, lwork: CLPK_integer,
            info: *mut CLPK_integer) -> c_int;

    pub fn chegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_complex, lda: *const CLPK_integer,
            b: *mut CLPK_complex, ldb: *const CLPK_integer, w: CLPK_real,
            work: CLPK_complex, lwork: CLPK_integer, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhegv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, a: *mut CLPK_doublecomplex, lda: *const CLPK_integer,
            b: *mut CLPK_doublecomplex, ldb: *const CLPK_integer,
            w: CLPK_doublereal, work: CLPK_doublecomplex,
            lwork: CLPK_integer, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn sspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_real, bp: CLPK_real,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dspgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublereal, bp: CLPK_doublereal,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_complex, bp: CLPK_complex,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhpgv_(itype: CLPK_integer, jobz: c_char, uplo: c_char,
            n: *const CLPK_integer, ap: CLPK_doublecomplex,
            bp: CLPK_doublecomplex, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn ssbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_real,
            ldab: CLPK_integer, bb: CLPK_real, ldbb: CLPK_integer,
            w: CLPK_real, z: CLPK_real, ldz: CLPK_integer,
            work: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn dsbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_doublereal,
            ldab: CLPK_integer, bb: CLPK_doublereal, ldbb: CLPK_integer,
            w: CLPK_doublereal, z: CLPK_doublereal, ldz: CLPK_integer,
            work: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;

    pub fn chbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_complex,
            ldab: CLPK_integer, bb: CLPK_complex, ldbb: CLPK_integer,
            w: CLPK_real, z: CLPK_complex, ldz: CLPK_integer,
            work: CLPK_complex, rwork: CLPK_real,
            info: *mut CLPK_integer) -> c_int;
    pub fn zhbgv_(jobz: c_char, uplo: c_char, n: *const CLPK_integer,
            ka: *mut CLPK_integer, kb: CLPK_integer, ab: CLPK_doublecomplex,
            ldab: CLPK_integer, bb: CLPK_doublecomplex,
            ldbb: CLPK_integer, w: CLPK_doublereal,
            z: CLPK_doublecomplex, ldz: CLPK_integer,
            work: CLPK_doublecomplex, rwork: CLPK_doublereal,
            info: *mut CLPK_integer) -> c_int;
}
<|endoftext|>