<commit_before>//! Implementation of find-usages functionality.
//!
//! It is based on the standard ide trick: first, we run a fast text search to
//! get a super-set of matches. Then, we we confirm each match using precise
//! name resolution.

use std::mem;

use hir::{DefWithBody, HasSource, ModuleSource, Semantics};
use once_cell::unsync::Lazy;
use ra_db::{FileId, FileRange, SourceDatabaseExt};
use ra_prof::profile;
use ra_syntax::{
    algo::find_node_at_offset, ast, match_ast, AstNode, TextRange, TextUnit, TokenAtOffset,
};
use rustc_hash::FxHashMap;
use test_utils::tested_by;

use crate::{
    defs::{classify_name_ref, Definition, NameRefClass},
    RootDatabase,
};

#[derive(Debug, Clone)]
pub struct Reference {
    pub file_range: FileRange,
    pub kind: ReferenceKind,
    pub access: Option<ReferenceAccess>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ReferenceKind {
    StructFieldShorthandForField,
    StructFieldShorthandForLocal,
    StructLiteral,
    Other,
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ReferenceAccess {
    Read,
    Write,
}

/// Generally, `search_scope` returns files that might contain references for the element.
/// For `pub(crate)` things it's a crate, for `pub` things it's a crate and dependant crates.
/// In some cases, the location of the references is known to within a `TextRange`,
/// e.g. for things like local variables.
pub struct SearchScope {
    entries: FxHashMap<FileId, Option<TextRange>>,
}

impl SearchScope {
    fn new(entries: FxHashMap<FileId, Option<TextRange>>) -> SearchScope {
        SearchScope { entries }
    }

    pub fn empty() -> SearchScope {
        SearchScope::new(FxHashMap::default())
    }

    pub fn single_file(file: FileId) -> SearchScope {
        SearchScope::new(std::iter::once((file, None)).collect())
    }

    pub fn intersection(&self, other: &SearchScope) -> SearchScope {
        let (mut small, mut large) = (&self.entries, &other.entries);
        if small.len() > large.len() {
            mem::swap(&mut small, &mut large)
        }

        let res = small
            .iter()
            .filter_map(|(file_id, r1)| {
                let r2 = large.get(file_id)?;
                let r = intersect_ranges(*r1, *r2)?;
                Some((*file_id, r))
            })
            .collect();

        return SearchScope::new(res);

        fn intersect_ranges(
            r1: Option<TextRange>,
            r2: Option<TextRange>,
        ) -> Option<Option<TextRange>> {
            match (r1, r2) {
                (None, r) | (r, None) => Some(r),
                (Some(r1), Some(r2)) => {
                    let r = r1.intersection(&r2)?;
                    Some(Some(r))
                }
            }
        }
    }
}

impl IntoIterator for SearchScope {
    type Item = (FileId, Option<TextRange>);
    type IntoIter = std::collections::hash_map::IntoIter<FileId, Option<TextRange>>;

    fn into_iter(self) -> Self::IntoIter {
        self.entries.into_iter()
    }
}

impl Definition {
    fn search_scope(&self, db: &RootDatabase) -> SearchScope {
        let _p = profile("search_scope");
        let module = match self.module(db) {
            Some(it) => it,
            None => return SearchScope::empty(),
        };
        let module_src = module.definition_source(db);
        let file_id = module_src.file_id.original_file(db);

        if let Definition::Local(var) = self {
            let range = match var.parent(db) {
                DefWithBody::Function(f) => f.source(db).value.syntax().text_range(),
                DefWithBody::Const(c) => c.source(db).value.syntax().text_range(),
                DefWithBody::Static(s) => s.source(db).value.syntax().text_range(),
            };
            let mut res = FxHashMap::default();
            res.insert(file_id, Some(range));
            return SearchScope::new(res);
        }

        let vis = self.visibility(db).as_ref().map(|v| v.syntax().to_string()).unwrap_or_default();

        if vis.as_str() == "pub(super)" {
            if let Some(parent_module) = module.parent(db) {
                let mut res = FxHashMap::default();
                let parent_src = parent_module.definition_source(db);
                let file_id = parent_src.file_id.original_file(db);

                match parent_src.value {
                    ModuleSource::Module(m) => {
                        let range = Some(m.syntax().text_range());
                        res.insert(file_id, range);
                    }
                    ModuleSource::SourceFile(_) => {
                        res.insert(file_id, None);
                        res.extend(parent_module.children(db).map(|m| {
                            let src = m.definition_source(db);
                            (src.file_id.original_file(db), None)
                        }));
                    }
                }
                return SearchScope::new(res);
            }
        }

        if vis.as_str() != "" {
            let source_root_id = db.file_source_root(file_id);
            let source_root = db.source_root(source_root_id);
            let mut res = source_root.walk().map(|id| (id, None)).collect::<FxHashMap<_, _>>();

            // FIXME: add "pub(in path)"

            if vis.as_str() == "pub(crate)" {
                return SearchScope::new(res);
            }
            if vis.as_str() == "pub" {
                let krate = module.krate();
                for rev_dep in krate.reverse_dependencies(db) {
                    let root_file = rev_dep.root_file(db);
                    let source_root_id = db.file_source_root(root_file);
                    let source_root = db.source_root(source_root_id);
                    res.extend(source_root.walk().map(|id| (id, None)));
                }
                return SearchScope::new(res);
            }
        }

        let mut res = FxHashMap::default();
        let range = match module_src.value {
            ModuleSource::Module(m) => Some(m.syntax().text_range()),
            ModuleSource::SourceFile(_) => None,
        };
        res.insert(file_id, range);
        SearchScope::new(res)
    }

    pub fn find_usages(
        &self,
        db: &RootDatabase,
        search_scope: Option<SearchScope>,
    ) -> Vec<Reference> {
        let _p = profile("Definition::find_usages");

        let search_scope = {
            let base = self.search_scope(db);
            match search_scope {
                None => base,
                Some(scope) => base.intersection(&scope),
            }
        };

        let name = match self.name(db) {
            None => return Vec::new(),
            Some(it) => it.to_string(),
        };

        let pat = name.as_str();
        let mut refs = vec![];

        for (file_id, search_range) in search_scope {
            let text = db.file_text(file_id);
            let search_range =
                search_range.unwrap_or(TextRange::offset_len(0.into(), TextUnit::of_str(&text)));

            let sema = Semantics::new(db);
            let tree = Lazy::new(|| sema.parse(file_id).syntax().clone());

            for (idx, _) in text.match_indices(pat) {
                let offset = TextUnit::from_usize(idx);
                if !search_range.contains_inclusive(offset) {
                    tested_by!(search_filters_by_range; force);
                    continue;
                }

                let name_ref =
                    if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&tree, offset) {
                        name_ref
                    } else {
                        // Handle macro token cases
                        let token = match tree.token_at_offset(offset) {
                            TokenAtOffset::None => continue,
                            TokenAtOffset::Single(t) => t,
                            TokenAtOffset::Between(_, t) => t,
                        };
                        let expanded = sema.descend_into_macros(token);
                        match ast::NameRef::cast(expanded.parent()) {
                            Some(name_ref) => name_ref,
                            _ => continue,
                        }
                    };

                // FIXME: reuse sb
                // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098

                match classify_name_ref(&sema, &name_ref) {
                    Some(NameRefClass::Definition(def)) if &def == self => {
                        let kind = if is_record_lit_name_ref(&name_ref)
                            || is_call_expr_name_ref(&name_ref)
                        {
                            ReferenceKind::StructLiteral
                        } else {
                            ReferenceKind::Other
                        };

                        let file_range = sema.original_range(name_ref.syntax());
                        refs.push(Reference {
                            file_range,
                            kind,
                            access: reference_access(&def, &name_ref),
                        });
                    }
                    Some(NameRefClass::FieldShorthand { local, field }) => {
                        match self {
                            Definition::StructField(_) if &field == self => refs.push(Reference {
                                file_range: sema.original_range(name_ref.syntax()),
                                kind: ReferenceKind::StructFieldShorthandForField,
                                access: reference_access(&field, &name_ref),
                            }),
                            Definition::Local(l) if &local == l => refs.push(Reference {
                                file_range: sema.original_range(name_ref.syntax()),
                                kind: ReferenceKind::StructFieldShorthandForLocal,
                                access: reference_access(&Definition::Local(local), &name_ref),
                            }),

                            _ => {} // not a usage
                        };
                    }
                    _ => {} // not a usage
                }
            }
        }
        refs
    }
}

fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> {
    // Only Locals and Fields have accesses for now.
    match def {
        Definition::Local(_) | Definition::StructField(_) => {}
        _ => return None,
    };

    let mode = name_ref.syntax().ancestors().find_map(|node| {
        match_ast! {
            match (node) {
                ast::BinExpr(expr) => {
                    if expr.op_kind()?.is_assignment() {
                        // If the variable or field ends on the LHS's end then it's a Write (covers fields and locals).
                        // FIXME: This is not terribly accurate.
                        if let Some(lhs) = expr.lhs() {
                            if lhs.syntax().text_range().end() == name_ref.syntax().text_range().end() {
                                return Some(ReferenceAccess::Write);
                            }
                        }
                    }
                    Some(ReferenceAccess::Read)
                },
                _ => {None}
            }
        }
    });

    // Default Locals and Fields to read
    mode.or(Some(ReferenceAccess::Read))
}

fn is_call_expr_name_ref(name_ref: &ast::NameRef) -> bool {
    name_ref
        .syntax()
        .ancestors()
        .find_map(ast::CallExpr::cast)
        .and_then(|c| match c.expr()? {
            ast::Expr::PathExpr(p) => {
                Some(p.path()?.segment()?.name_ref().as_ref() == Some(name_ref))
            }
            _ => None,
        })
        .unwrap_or(false)
}

fn is_record_lit_name_ref(name_ref: &ast::NameRef) -> bool {
    name_ref
        .syntax()
        .ancestors()
        .find_map(ast::RecordLit::cast)
        .and_then(|l| l.path())
        .and_then(|p| p.segment())
        .map(|p| p.name_ref().as_ref() == Some(name_ref))
        .unwrap_or(false)
}
<commit_msg>Refactor search<commit_after>//! Implementation of find-usages functionality.
//!
//! It is based on the standard ide trick: first, we run a fast text search to
//! get a super-set of matches. Then, we we confirm each match using precise
//! name resolution.

use std::mem;

use hir::{DefWithBody, HasSource, ModuleSource, Semantics};
use once_cell::unsync::Lazy;
use ra_db::{FileId, FileRange, SourceDatabaseExt};
use ra_prof::profile;
use ra_syntax::{ast, match_ast, AstNode, TextRange, TextUnit};
use rustc_hash::FxHashMap;
use test_utils::tested_by;

use crate::{
    defs::{classify_name_ref, Definition, NameRefClass},
    RootDatabase,
};

#[derive(Debug, Clone)]
pub struct Reference {
    pub file_range: FileRange,
    pub kind: ReferenceKind,
    pub access: Option<ReferenceAccess>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum ReferenceKind {
    StructFieldShorthandForField,
    StructFieldShorthandForLocal,
    StructLiteral,
    Other,
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ReferenceAccess {
    Read,
    Write,
}

/// Generally, `search_scope` returns files that might contain references for the element.
/// For `pub(crate)` things it's a crate, for `pub` things it's a crate and dependant crates.
/// In some cases, the location of the references is known to within a `TextRange`,
/// e.g. for things like local variables.
pub struct SearchScope {
    entries: FxHashMap<FileId, Option<TextRange>>,
}

impl SearchScope {
    fn new(entries: FxHashMap<FileId, Option<TextRange>>) -> SearchScope {
        SearchScope { entries }
    }

    pub fn empty() -> SearchScope {
        SearchScope::new(FxHashMap::default())
    }

    pub fn single_file(file: FileId) -> SearchScope {
        SearchScope::new(std::iter::once((file, None)).collect())
    }

    pub fn intersection(&self, other: &SearchScope) -> SearchScope {
        let (mut small, mut large) = (&self.entries, &other.entries);
        if small.len() > large.len() {
            mem::swap(&mut small, &mut large)
        }

        let res = small
            .iter()
            .filter_map(|(file_id, r1)| {
                let r2 = large.get(file_id)?;
                let r = intersect_ranges(*r1, *r2)?;
                Some((*file_id, r))
            })
            .collect();

        return SearchScope::new(res);

        fn intersect_ranges(
            r1: Option<TextRange>,
            r2: Option<TextRange>,
        ) -> Option<Option<TextRange>> {
            match (r1, r2) {
                (None, r) | (r, None) => Some(r),
                (Some(r1), Some(r2)) => {
                    let r = r1.intersection(&r2)?;
                    Some(Some(r))
                }
            }
        }
    }
}

impl IntoIterator for SearchScope {
    type Item = (FileId, Option<TextRange>);
    type IntoIter = std::collections::hash_map::IntoIter<FileId, Option<TextRange>>;

    fn into_iter(self) -> Self::IntoIter {
        self.entries.into_iter()
    }
}

impl Definition {
    fn search_scope(&self, db: &RootDatabase) -> SearchScope {
        let _p = profile("search_scope");
        let module = match self.module(db) {
            Some(it) => it,
            None => return SearchScope::empty(),
        };
        let module_src = module.definition_source(db);
        let file_id = module_src.file_id.original_file(db);

        if let Definition::Local(var) = self {
            let range = match var.parent(db) {
                DefWithBody::Function(f) => f.source(db).value.syntax().text_range(),
                DefWithBody::Const(c) => c.source(db).value.syntax().text_range(),
                DefWithBody::Static(s) => s.source(db).value.syntax().text_range(),
            };
            let mut res = FxHashMap::default();
            res.insert(file_id, Some(range));
            return SearchScope::new(res);
        }

        let vis = self.visibility(db).as_ref().map(|v| v.syntax().to_string()).unwrap_or_default();

        if vis.as_str() == "pub(super)" {
            if let Some(parent_module) = module.parent(db) {
                let mut res = FxHashMap::default();
                let parent_src = parent_module.definition_source(db);
                let file_id = parent_src.file_id.original_file(db);

                match parent_src.value {
                    ModuleSource::Module(m) => {
                        let range = Some(m.syntax().text_range());
                        res.insert(file_id, range);
                    }
                    ModuleSource::SourceFile(_) => {
                        res.insert(file_id, None);
                        res.extend(parent_module.children(db).map(|m| {
                            let src = m.definition_source(db);
                            (src.file_id.original_file(db), None)
                        }));
                    }
                }
                return SearchScope::new(res);
            }
        }

        if vis.as_str() != "" {
            let source_root_id = db.file_source_root(file_id);
            let source_root = db.source_root(source_root_id);
            let mut res = source_root.walk().map(|id| (id, None)).collect::<FxHashMap<_, _>>();

            // FIXME: add "pub(in path)"

            if vis.as_str() == "pub(crate)" {
                return SearchScope::new(res);
            }
            if vis.as_str() == "pub" {
                let krate = module.krate();
                for rev_dep in krate.reverse_dependencies(db) {
                    let root_file = rev_dep.root_file(db);
                    let source_root_id = db.file_source_root(root_file);
                    let source_root = db.source_root(source_root_id);
                    res.extend(source_root.walk().map(|id| (id, None)));
                }
                return SearchScope::new(res);
            }
        }

        let mut res = FxHashMap::default();
        let range = match module_src.value {
            ModuleSource::Module(m) => Some(m.syntax().text_range()),
            ModuleSource::SourceFile(_) => None,
        };
        res.insert(file_id, range);
        SearchScope::new(res)
    }

    pub fn find_usages(
        &self,
        db: &RootDatabase,
        search_scope: Option<SearchScope>,
    ) -> Vec<Reference> {
        let _p = profile("Definition::find_usages");

        let search_scope = {
            let base = self.search_scope(db);
            match search_scope {
                None => base,
                Some(scope) => base.intersection(&scope),
            }
        };

        let name = match self.name(db) {
            None => return Vec::new(),
            Some(it) => it.to_string(),
        };

        let pat = name.as_str();
        let mut refs = vec![];

        for (file_id, search_range) in search_scope {
            let text = db.file_text(file_id);
            let search_range =
                search_range.unwrap_or(TextRange::offset_len(0.into(), TextUnit::of_str(&text)));

            let sema = Semantics::new(db);
            let tree = Lazy::new(|| sema.parse(file_id).syntax().clone());

            for (idx, _) in text.match_indices(pat) {
                let offset = TextUnit::from_usize(idx);
                if !search_range.contains_inclusive(offset) {
                    tested_by!(search_filters_by_range; force);
                    continue;
                }

                let name_ref: ast::NameRef =
                    if let Some(name_ref) = sema.find_node_at_offset_with_descend(&tree, offset) {
                        name_ref
                    } else {
                        continue;
                    };

                // FIXME: reuse sb
                // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098

                match classify_name_ref(&sema, &name_ref) {
                    Some(NameRefClass::Definition(def)) if &def == self => {
                        let kind = if is_record_lit_name_ref(&name_ref)
                            || is_call_expr_name_ref(&name_ref)
                        {
                            ReferenceKind::StructLiteral
                        } else {
                            ReferenceKind::Other
                        };

                        let file_range = sema.original_range(name_ref.syntax());
                        refs.push(Reference {
                            file_range,
                            kind,
                            access: reference_access(&def, &name_ref),
                        });
                    }
                    Some(NameRefClass::FieldShorthand { local, field }) => {
                        match self {
                            Definition::StructField(_) if &field == self => refs.push(Reference {
                                file_range: sema.original_range(name_ref.syntax()),
                                kind: ReferenceKind::StructFieldShorthandForField,
                                access: reference_access(&field, &name_ref),
                            }),
                            Definition::Local(l) if &local == l => refs.push(Reference {
                                file_range: sema.original_range(name_ref.syntax()),
                                kind: ReferenceKind::StructFieldShorthandForLocal,
                                access: reference_access(&Definition::Local(local), &name_ref),
                            }),

                            _ => {} // not a usage
                        };
                    }
                    _ => {} // not a usage
                }
            }
        }
        refs
    }
}

fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> {
    // Only Locals and Fields have accesses for now.
    match def {
        Definition::Local(_) | Definition::StructField(_) => {}
        _ => return None,
    };

    let mode = name_ref.syntax().ancestors().find_map(|node| {
        match_ast! {
            match (node) {
                ast::BinExpr(expr) => {
                    if expr.op_kind()?.is_assignment() {
                        // If the variable or field ends on the LHS's end then it's a Write (covers fields and locals).
                        // FIXME: This is not terribly accurate.
                        if let Some(lhs) = expr.lhs() {
                            if lhs.syntax().text_range().end() == name_ref.syntax().text_range().end() {
                                return Some(ReferenceAccess::Write);
                            }
                        }
                    }
                    Some(ReferenceAccess::Read)
                },
                _ => {None}
            }
        }
    });

    // Default Locals and Fields to read
    mode.or(Some(ReferenceAccess::Read))
}

fn is_call_expr_name_ref(name_ref: &ast::NameRef) -> bool {
    name_ref
        .syntax()
        .ancestors()
        .find_map(ast::CallExpr::cast)
        .and_then(|c| match c.expr()? {
            ast::Expr::PathExpr(p) => {
                Some(p.path()?.segment()?.name_ref().as_ref() == Some(name_ref))
            }
            _ => None,
        })
        .unwrap_or(false)
}

fn is_record_lit_name_ref(name_ref: &ast::NameRef) -> bool {
    name_ref
        .syntax()
        .ancestors()
        .find_map(ast::RecordLit::cast)
        .and_then(|l| l.path())
        .and_then(|p| p.segment())
        .map(|p| p.name_ref().as_ref() == Some(name_ref))
        .unwrap_or(false)
}
<|endoftext|>


<commit_before>use std::time::Instant;

use cubes_rs::{choose_puzzle, solve, write_obj_file, write_obj_file_solution};

fn main() -> Result<(), cubes_rs::Error> {
    let now = Instant::now();
    env_logger::init();

    let (puzzle, puzzle_string) = choose_puzzle()?;
    write_obj_file(&puzzle, &puzzle_string)?;

    let solutions = solve(puzzle);
    for solution in &solutions {
        println!("{:}", solution);
    }
    write_obj_file_solution(&solutions[0], &puzzle_string)?;

    let elapsed_time = now.elapsed();
    log::info!(
        "Running the program took {} seconds.",
        elapsed_time.as_micros() as f64 / 1_000_000.0
    );

    Ok(())
}
<commit_msg>Use as_secs_f64.<commit_after>use std::time::Instant;

use cubes_rs::{choose_puzzle, solve, write_obj_file, write_obj_file_solution};

fn main() -> Result<(), cubes_rs::Error> {
    let now = Instant::now();
    env_logger::init();

    let (puzzle, puzzle_string) = choose_puzzle()?;
    write_obj_file(&puzzle, &puzzle_string)?;

    let solutions = solve(puzzle);
    for solution in &solutions {
        println!("{:}", solution);
    }
    write_obj_file_solution(&solutions[0], &puzzle_string)?;

    let elapsed_time = now.elapsed();
    log::info!(
        "Running the program took {} seconds.",
        elapsed_time.as_secs_f64(),
    );

    Ok(())
}
<|endoftext|>


<commit_before>extern crate toml;
#[macro_use] extern crate log;
#[macro_use] extern crate semver;

#[macro_use] extern crate libimagstore;

module_entry_path_mod!("counter", "0.1.0");

pub mod counter;
pub mod error;
pub mod result;

<commit_msg>Enable lints<commit_after>#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate toml;
#[macro_use] extern crate log;
#[macro_use] extern crate semver;

#[macro_use] extern crate libimagstore;

module_entry_path_mod!("counter", "0.1.0");

pub mod counter;
pub mod error;
pub mod result;

<|endoftext|>


<commit_before>use tokio::codec::{Encoder, Decoder};
use std::io::{Error, ErrorKind};
use bytes::{BufMut, BytesMut};

// 5 MiB limit
const MAX_MSG_LEN: u32 = 5_242_880;
// 512 bits should be way more than enough
const MAX_ID_LEN: u8 = 64;

#[derive(Debug)]
pub struct Payload {
    id: BytesMut,
    msg: BytesMut
}

#[derive(Default, Debug)]
pub struct Codec {
    id_len: u8,
    msg_len: u32
}

impl Codec {
    pub fn new() -> Codec {
        Codec::default()
    }
}

impl Encoder for Codec {
    type Item = Payload;
    type Error = Error;

    fn encode(&mut self, item: Self::Item, buf: &mut BytesMut) -> Result<(), Error> {
        assert!(item.id.len() < usize::from(MAX_ID_LEN));
        assert!((item.msg.len() as u32) < MAX_MSG_LEN);
        {
            let total_len = item.id.len() + item.msg.len() + 5;
            buf.reserve(total_len + 5);
        }
        buf.put_u8(item.id.len() as u8);
        buf.put_u32_be(item.msg.len() as u32);
        buf.put(item.id);
        buf.put(item.msg);
        Ok(())
    }
}

impl Decoder for Codec {
    type Item = Payload;
    type Error = Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
        if self.id_len == 0 && self.msg_len == 0 && buf.len() >= 5 {
            let buf = buf.split_to(5);
            self.id_len = buf[0];
            self.msg_len = u32::from_be_bytes([buf[1], buf[2], buf[3], buf[4]]);
            if self.id_len > MAX_ID_LEN {
                return Err(Error::new(ErrorKind::Other, format!("id must be <={} bytes", MAX_ID_LEN)))
            } else if self.msg_len > MAX_MSG_LEN {
                return Err(Error::new(ErrorKind::Other, format!("msg must be <={} bytes", MAX_MSG_LEN)))
            }
        }
        if self.id_len != 0 && self.msg_len != 0
                && buf.len() >= usize::from(self.id_len) + (self.msg_len as usize) {
            let id_len = self.id_len;
            self.id_len = 0;

            let msg_len = self.msg_len;
            self.msg_len = 0;

            let id = buf.split_to(id_len as usize);
            let msg = buf.split_to(msg_len as usize);
            Ok(Some(Payload { id, msg }))
        } else {
            Ok(None)
        }
    }
}

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

    macro_rules! assert_decode {
        ($codec:expr, $bytes:expr, $id:expr, $msg:expr) => {
            {
                let res = $codec.decode(&mut $bytes).unwrap();
                assert!(res.is_some(), "decoding failure, expected Ok");
                let res = res.expect("decoding failure, expected payload");
                assert_eq!(res.id, $id, "id mismatch");
                assert_eq!(res.msg, $msg, "msg mismatch");
            }
        };
    }

    #[test]
    fn test_encode_full_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::new();
        codec.encode(Payload {
            id: vec![0, 1, 2, 3, 4, 5].into(),
            msg: vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245].into()
        }, &mut bytes).unwrap();
        assert_eq!(bytes, vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 // Msg
        ]);
    }

    #[test]
    fn test_decode_full_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 // Msg
        ]);

        assert_decode!(codec, bytes,
                        vec![0, 1, 2, 3, 4, 5],
                        vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);
    }

    #[test]
    fn test_decode_multipart_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248 // Msg
        ]);
        let res = codec.decode(&mut bytes).unwrap();
        assert!(res.is_none());

        bytes.reserve(3);
        bytes.put_slice(&vec![247, 246, 245]);
        assert_decode!(codec, bytes,
                        vec![0, 1, 2, 3, 4, 5],
                        vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);
    }

    #[test]
    fn test_decode_multiple_multipart_frames() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, // Msg
            3 // ID len
        ]);
        assert_decode!(codec, bytes,
                vec![0, 1, 2, 3, 4, 5],
                vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);

        // Ensure the codec data is correct
        assert_eq!(bytes.len(), 1);
        assert_eq!(codec.id_len, 0);
        assert_eq!(codec.msg_len, 0);

        bytes.reserve(4);
        bytes.put_slice(&vec![0, 0, 0, 5]); // Write msg len
        let res = codec.decode(&mut bytes).unwrap();
        assert!(res.is_none());

        assert_eq!(bytes.len(), 0);
        assert_eq!(codec.id_len, 3);
        assert_eq!(codec.msg_len, 5);

        bytes.reserve(8);
        bytes.put_slice(&vec![
            1, 1, 1, // ID
            2, 2, 2, 2, 2 // Msg
        ]);
        assert_decode!(codec, bytes,
                vec![1, 1, 1],
                vec![2, 2, 2, 2, 2]);
    }

    #[test]
    fn test_decode_multiple_full_frames() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            // First payload
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, // Msg
            // Second payload
            3,
            0, 0, 0, 4,
            1, 1, 1,
            2, 2, 2, 2,
            // Third payload
            4,
            0, 0, 0, 5,
            3, 3, 3, 3,
            4, 4, 4, 4, 4
        ]);

        assert_decode!(codec, bytes,
                vec![0, 1, 2, 3, 4, 5],
                vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);

        assert_decode!(codec, bytes,
                vec![1, 1, 1],
                vec![2, 2, 2, 2]);

        assert_decode!(codec, bytes,
                vec![3, 3, 3, 3],
                vec![4, 4, 4, 4, 4]);

        assert_eq!(bytes.len(), 0);
        assert_eq!(codec.id_len, 0);
        assert_eq!(codec.msg_len, 0);
    }
}
<commit_msg>Add tests for max ID and msg length<commit_after>use tokio::codec::{Encoder, Decoder};
use std::io::{Error, ErrorKind};
use bytes::{BufMut, BytesMut};

// 5 MiB limit
const MAX_MSG_LEN: u32 = 5_242_880;
// 512 bits should be way more than enough
const MAX_ID_LEN: u8 = 64;

#[derive(Debug)]
pub struct Payload {
    id: BytesMut,
    msg: BytesMut
}

#[derive(Default, Debug)]
pub struct Codec {
    id_len: u8,
    msg_len: u32
}

impl Codec {
    pub fn new() -> Codec {
        Codec::default()
    }
}

impl Encoder for Codec {
    type Item = Payload;
    type Error = Error;

    fn encode(&mut self, item: Self::Item, buf: &mut BytesMut) -> Result<(), Error> {
        assert!(item.id.len() < usize::from(MAX_ID_LEN));
        assert!((item.msg.len() as u32) < MAX_MSG_LEN);
        {
            let total_len = item.id.len() + item.msg.len() + 5;
            buf.reserve(total_len + 5);
        }
        buf.put_u8(item.id.len() as u8);
        buf.put_u32_be(item.msg.len() as u32);
        buf.put(item.id);
        buf.put(item.msg);
        Ok(())
    }
}

impl Decoder for Codec {
    type Item = Payload;
    type Error = Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
        if self.id_len == 0 && self.msg_len == 0 && buf.len() >= 5 {
            let buf = buf.split_to(5);
            self.id_len = buf[0];
            self.msg_len = u32::from_be_bytes([buf[1], buf[2], buf[3], buf[4]]);
            if self.id_len > MAX_ID_LEN {
                return Err(Error::new(ErrorKind::Other, format!("id must be <={} bytes", MAX_ID_LEN)))
            } else if self.msg_len > MAX_MSG_LEN {
                return Err(Error::new(ErrorKind::Other, format!("msg must be <={} bytes", MAX_MSG_LEN)))
            }
        }
        if self.id_len != 0 && self.msg_len != 0
                && buf.len() >= usize::from(self.id_len) + (self.msg_len as usize) {
            let id_len = self.id_len;
            self.id_len = 0;

            let msg_len = self.msg_len;
            self.msg_len = 0;

            let id = buf.split_to(id_len as usize);
            let msg = buf.split_to(msg_len as usize);
            Ok(Some(Payload { id, msg }))
        } else {
            Ok(None)
        }
    }
}

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

    macro_rules! assert_decode {
        ($codec:expr, $bytes:expr, $id:expr, $msg:expr) => {
            {
                let res = $codec.decode(&mut $bytes).unwrap();
                assert!(res.is_some(), "decoding failure, expected Ok");
                let res = res.expect("decoding failure, expected payload");
                assert_eq!(res.id, $id, "id mismatch");
                assert_eq!(res.msg, $msg, "msg mismatch");
            }
        };
    }

    #[test]
    fn test_max_id_len() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            MAX_ID_LEN + 1,
            0, 0, 0, 0
        ]);
        let err = codec.decode(&mut bytes).unwrap_err();
        assert_eq!(err.description(), format!("id must be <={} bytes", MAX_ID_LEN));
    }

    #[test]
    fn test_max_msg_len() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            1,
            255, 255, 255, 255
        ]);
        let err = codec.decode(&mut bytes).unwrap_err();
        assert_eq!(err.description(), format!("msg must be <={} bytes", MAX_MSG_LEN));
    }

    #[test]
    fn test_encode_full_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::new();
        codec.encode(Payload {
            id: vec![0, 1, 2, 3, 4, 5].into(),
            msg: vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245].into()
        }, &mut bytes).unwrap();
        assert_eq!(bytes, vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 // Msg
        ]);
    }

    #[test]
    fn test_decode_full_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 // Msg
        ]);

        assert_decode!(codec, bytes,
                        vec![0, 1, 2, 3, 4, 5],
                        vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);
    }

    #[test]
    fn test_decode_multipart_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248 // Msg
        ]);
        let res = codec.decode(&mut bytes).unwrap();
        assert!(res.is_none());

        bytes.reserve(3);
        bytes.put_slice(&vec![247, 246, 245]);
        assert_decode!(codec, bytes,
                        vec![0, 1, 2, 3, 4, 5],
                        vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);
    }

    #[test]
    fn test_decode_multiple_multipart_frames() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, // Msg
            3 // ID len
        ]);
        assert_decode!(codec, bytes,
                vec![0, 1, 2, 3, 4, 5],
                vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);

        // Ensure the codec data is correct
        assert_eq!(bytes.len(), 1);
        assert_eq!(codec.id_len, 0);
        assert_eq!(codec.msg_len, 0);

        bytes.reserve(4);
        bytes.put_slice(&vec![0, 0, 0, 5]); // Write msg len
        let res = codec.decode(&mut bytes).unwrap();
        assert!(res.is_none());

        assert_eq!(bytes.len(), 0);
        assert_eq!(codec.id_len, 3);
        assert_eq!(codec.msg_len, 5);

        bytes.reserve(8);
        bytes.put_slice(&vec![
            1, 1, 1, // ID
            2, 2, 2, 2, 2 // Msg
        ]);
        assert_decode!(codec, bytes,
                vec![1, 1, 1],
                vec![2, 2, 2, 2, 2]);
    }

    #[test]
    fn test_decode_multiple_full_frames() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            // First payload
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, // Msg
            // Second payload
            3,
            0, 0, 0, 4,
            1, 1, 1,
            2, 2, 2, 2,
            // Third payload
            4,
            0, 0, 0, 5,
            3, 3, 3, 3,
            4, 4, 4, 4, 4
        ]);

        assert_decode!(codec, bytes,
                vec![0, 1, 2, 3, 4, 5],
                vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);

        assert_decode!(codec, bytes,
                vec![1, 1, 1],
                vec![2, 2, 2, 2]);

        assert_decode!(codec, bytes,
                vec![3, 3, 3, 3],
                vec![4, 4, 4, 4, 4]);

        assert_eq!(bytes.len(), 0);
        assert_eq!(codec.id_len, 0);
        assert_eq!(codec.msg_len, 0);
    }
}
<|endoftext|>


<commit_before>use rustc_index::vec::Idx;

pub mod dominators;
pub mod implementation;
pub mod iterate;
mod reference;
pub mod scc;
pub mod vec_graph;

#[cfg(test)]
mod tests;

pub trait DirectedGraph {
    type Node: Idx;
}

pub trait WithNumNodes: DirectedGraph {
    fn num_nodes(&self) -> usize;
}

pub trait WithNumEdges: DirectedGraph {
    fn num_edges(&self) -> usize;
}

pub trait WithSuccessors: DirectedGraph
where
    Self: for<'graph> GraphSuccessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
    fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter;

    fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self>
    where
        Self: WithNumNodes,
    {
        iterate::DepthFirstSearch::new(self, from)
    }
}

#[allow(unused_lifetimes)]
pub trait GraphSuccessors<'graph> {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
}

pub trait WithPredecessors: DirectedGraph
where
    Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
    fn predecessors(&self, node: Self::Node) -> <Self as GraphPredecessors<'_>>::Iter;
}

#[allow(unused_lifetimes)]
pub trait GraphPredecessors<'graph> {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
}

pub trait WithStartNode: DirectedGraph {
    fn start_node(&self) -> Self::Node;
}

pub trait ControlFlowGraph:
    DirectedGraph + WithStartNode + WithPredecessors + WithStartNode + WithSuccessors + WithNumNodes
{
    // convenient trait
}

impl<T> ControlFlowGraph for T where
    T: DirectedGraph
        + WithStartNode
        + WithPredecessors
        + WithStartNode
        + WithSuccessors
        + WithNumNodes
{
}

/// Returns `true` if the graph has a cycle that is reachable from the start node.
pub fn is_cyclic<G>(graph: &G) -> bool
where
    G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
{
    iterate::TriColorDepthFirstSearch::new(graph)
        .run_from_start(&mut iterate::CycleDetector)
        .is_some()
}
<commit_msg>Remove duplicate trait bounds in `rustc_data_structures::graph`<commit_after>use rustc_index::vec::Idx;

pub mod dominators;
pub mod implementation;
pub mod iterate;
mod reference;
pub mod scc;
pub mod vec_graph;

#[cfg(test)]
mod tests;

pub trait DirectedGraph {
    type Node: Idx;
}

pub trait WithNumNodes: DirectedGraph {
    fn num_nodes(&self) -> usize;
}

pub trait WithNumEdges: DirectedGraph {
    fn num_edges(&self) -> usize;
}

pub trait WithSuccessors: DirectedGraph
where
    Self: for<'graph> GraphSuccessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
    fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter;

    fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self>
    where
        Self: WithNumNodes,
    {
        iterate::DepthFirstSearch::new(self, from)
    }
}

#[allow(unused_lifetimes)]
pub trait GraphSuccessors<'graph> {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
}

pub trait WithPredecessors: DirectedGraph
where
    Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
{
    fn predecessors(&self, node: Self::Node) -> <Self as GraphPredecessors<'_>>::Iter;
}

#[allow(unused_lifetimes)]
pub trait GraphPredecessors<'graph> {
    type Item;
    type Iter: Iterator<Item = Self::Item>;
}

pub trait WithStartNode: DirectedGraph {
    fn start_node(&self) -> Self::Node;
}

pub trait ControlFlowGraph:
    DirectedGraph + WithStartNode + WithPredecessors + WithSuccessors + WithNumNodes
{
    // convenient trait
}

impl<T> ControlFlowGraph for T where
    T: DirectedGraph + WithStartNode + WithPredecessors + WithSuccessors + WithNumNodes
{
}

/// Returns `true` if the graph has a cycle that is reachable from the start node.
pub fn is_cyclic<G>(graph: &G) -> bool
where
    G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
{
    iterate::TriColorDepthFirstSearch::new(graph)
        .run_from_start(&mut iterate::CycleDetector)
        .is_some()
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    block::Block,
    common::{Payload, Round},
    quorum_cert::QuorumCert,
};
use executor_types::StateComputeResult;
use libra_crypto::hash::HashValue;
use libra_types::block_info::BlockInfo;
use std::fmt::{Display, Formatter};

/// ExecutedBlocks are managed in a speculative tree, the committed blocks form a chain. Besides
/// block data, each executed block also has other derived meta data which could be regenerated from
/// blocks.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ExecutedBlock {
    /// Block data that cannot be regenerated.
    block: Block,
    /// The state_compute_result is calculated for all the pending blocks prior to insertion to
    /// the tree. The execution results are not persisted: they're recalculated again for the
    /// pending blocks upon restart.
    state_compute_result: StateComputeResult,
}

impl Display for ExecutedBlock {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "{}", self.block())
    }
}

impl ExecutedBlock {
    pub fn new(block: Block, state_compute_result: StateComputeResult) -> Self {
        Self {
            block,
            state_compute_result,
        }
    }

    pub fn block(&self) -> &Block {
        &self.block
    }

    pub fn epoch(&self) -> u64 {
        self.block().epoch()
    }

    pub fn id(&self) -> HashValue {
        self.block().id()
    }

    pub fn payload(&self) -> Option<&Payload> {
        self.block().payload()
    }

    pub fn parent_id(&self) -> HashValue {
        self.quorum_cert().certified_block().id()
    }

    pub fn quorum_cert(&self) -> &QuorumCert {
        self.block().quorum_cert()
    }

    pub fn round(&self) -> Round {
        self.block().round()
    }

    pub fn timestamp_usecs(&self) -> u64 {
        self.block().timestamp_usecs()
    }

    pub fn compute_result(&self) -> &StateComputeResult {
        &self.state_compute_result
    }

    pub fn block_info(&self) -> BlockInfo {
        self.block().gen_block_info(
            self.compute_result().root_hash(),
            self.compute_result().version(),
            self.compute_result().epoch_state().clone(),
        )
    }
}
<commit_msg>Removing epoch from consensus/consensus-types/src/executed_block.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    block::Block,
    common::{Payload, Round},
    quorum_cert::QuorumCert,
};
use executor_types::StateComputeResult;
use libra_crypto::hash::HashValue;
use libra_types::block_info::BlockInfo;
use std::fmt::{Display, Formatter};

/// ExecutedBlocks are managed in a speculative tree, the committed blocks form a chain. Besides
/// block data, each executed block also has other derived meta data which could be regenerated from
/// blocks.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ExecutedBlock {
    /// Block data that cannot be regenerated.
    block: Block,
    /// The state_compute_result is calculated for all the pending blocks prior to insertion to
    /// the tree. The execution results are not persisted: they're recalculated again for the
    /// pending blocks upon restart.
    state_compute_result: StateComputeResult,
}

impl Display for ExecutedBlock {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        write!(f, "{}", self.block())
    }
}

impl ExecutedBlock {
    pub fn new(block: Block, state_compute_result: StateComputeResult) -> Self {
        Self {
            block,
            state_compute_result,
        }
    }

    pub fn block(&self) -> &Block {
        &self.block
    }

    pub fn id(&self) -> HashValue {
        self.block().id()
    }

    pub fn payload(&self) -> Option<&Payload> {
        self.block().payload()
    }

    pub fn parent_id(&self) -> HashValue {
        self.quorum_cert().certified_block().id()
    }

    pub fn quorum_cert(&self) -> &QuorumCert {
        self.block().quorum_cert()
    }

    pub fn round(&self) -> Round {
        self.block().round()
    }

    pub fn timestamp_usecs(&self) -> u64 {
        self.block().timestamp_usecs()
    }

    pub fn compute_result(&self) -> &StateComputeResult {
        &self.state_compute_result
    }

    pub fn block_info(&self) -> BlockInfo {
        self.block().gen_block_info(
            self.compute_result().root_hash(),
            self.compute_result().version(),
            self.compute_result().epoch_state().clone(),
        )
    }
}
<|endoftext|>


<commit_before>use helpers::*;

#[test]
fn integers() {
    assert_eval_err("(0 1 2)", unappliable_value_error(integer(0)));
}

#[test]
fn booleans() {
    assert_eval_err("(#t #f #t)", unappliable_value_error(bool(true)));
}

#[test]
#[should_fail]
fn atoms() {
    assert_eval_err("(a b c)", unbound_variable_error("a"));
}

#[test]
#[should_fail]
fn lists() {
    assert_eval_err("('(1))", unappliable_value_error(list(vec!(integer(1)))));
}

#[test]
#[should_fail]
fn dotted_lists() {
    assert_eval_err("('(1 . 2))", unappliable_value_error(dotted_list(vec!(integer(1)), integer(2))));
}
<commit_msg>Fixed pending tests on eval+application.<commit_after>use helpers::*;

#[test]
fn integers() {
    assert_eval_err("(0 1 2)", unappliable_value_error(integer(0)));
}

#[test]
fn booleans() {
    assert_eval_err("(#t #f #t)", unappliable_value_error(bool(true)));
}

#[test]
#[should_fail]
fn atoms() {
    assert_eval_err("(a b c)", unbound_variable_error("a"));
}

#[test]
fn lists() {
    assert_eval_err("('(1))", unappliable_value_error(list(vec!(atom("quote"),
                                                                list(vec!(integer(1)))))));
}

<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos::common::types::account_address_from_public_key;
use aptos_crypto::PrivateKey;
use aptos_sdk::move_types::language_storage::StructTag;
use aptos_transaction_builder::aptos_stdlib;
use aptos_types::account_address::AccountAddress;
use aptos_types::account_config::{AccountResource, CORE_CODE_ADDRESS};
use aptos_types::transaction::authenticator::AuthenticationKey;
use forge::Swarm;
use std::convert::TryFrom;
use std::str::FromStr;

use crate::smoke_test_environment::new_local_swarm_with_aptos;

#[tokio::test]
async fn test_get_index() {
    let mut swarm = new_local_swarm_with_aptos(1).await;
    let info = swarm.aptos_public_info();

    let resp = reqwest::get(info.url().to_owned()).await.unwrap();
    assert_eq!(reqwest::StatusCode::OK, resp.status());
}

#[tokio::test]
async fn test_basic_client() {
    let mut swarm = new_local_swarm_with_aptos(1).await;
    let mut info = swarm.aptos_public_info();

    info.client().get_ledger_information().await.unwrap();

    // TODO(Gas): double check if this is correct
    let mut account1 = info.create_and_fund_user_account(10_000).await.unwrap();
    // TODO(Gas): double check if this is correct
    let account2 = info.create_and_fund_user_account(10_000).await.unwrap();

    let tx = account1.sign_with_transaction_builder(
        info.transaction_factory()
            .payload(aptos_stdlib::aptos_coin_transfer(account2.address(), 1)),
    );
    let pending_txn = info.client().submit(&tx).await.unwrap().into_inner();

    info.client()
        .wait_for_transaction(&pending_txn)
        .await
        .unwrap();

    info.client()
        .get_transaction_by_hash(pending_txn.hash.into())
        .await
        .unwrap();

    info.client()
        .get_account_resources(CORE_CODE_ADDRESS)
        .await
        .unwrap();

    info.client().get_transactions(None, None).await.unwrap();
}

#[tokio::test]
async fn test_bcs() {
    // FIXME: Use swarm instead of local node
    // let mut swarm = new_local_swarm_with_aptos(1).await;
    //let mut info = swarm.aptos_public_info();
    //let client = info.client();
    let rest_api = reqwest::Url::parse("http://localhost:8080/v1").unwrap();
    let client = aptos_rest_client::Client::new(rest_api.clone());
    let faucet_client = aptos_rest_client::FaucetClient::new(
        reqwest::Url::parse("http://localhost:8081").unwrap(),
        rest_api,
    );

    // Create account
    let mut keygen = aptos_keygen::KeyGen::from_seed([0u8; 32]);
    let private_key = keygen.generate_ed25519_private_key();
    let public_key = private_key.public_key();
    let account = account_address_from_public_key(&public_key);

    // Fund account
    faucet_client.fund(account, 10000000).await.unwrap();

    // Check get account
    let account_resource = client.get_account_bcs(account).await.unwrap().into_inner();
    let expected_auth_key = AuthenticationKey::ed25519(&public_key);
    let onchain_auth_key =
        AuthenticationKey::try_from(account_resource.authentication_key()).unwrap();
    assert_eq!(expected_auth_key, onchain_auth_key);
    assert_eq!(0, account_resource.sequence_number());

    // Check get resources
    let resources = client
        .get_account_resources_bcs(account)
        .await
        .unwrap()
        .into_inner();
    let bytes = resources
        .get(&StructTag::from_str("0x1::account::Account").unwrap())
        .unwrap();
    let account_resource: AccountResource = bcs::from_bytes(bytes).unwrap();
    assert_eq!(0, account_resource.sequence_number());

    // Check Modules align
    let modules = client
        .get_account_modules(AccountAddress::ONE)
        .await
        .unwrap()
        .into_inner();
    let bcs_modules = client
        .get_account_modules_bcs(AccountAddress::ONE)
        .await
        .unwrap()
        .into_inner();

    assert_eq!(modules.len(), bcs_modules.len());
    let (module_id, _) = modules.iter().next().unwrap();
    assert_eq!(
        &modules.get(module_id).unwrap().bytecode.0,
        bcs_modules.get(module_id).unwrap()
    );
}
<commit_msg>[testsuite] Convert BCS smoke test to a real smoke test<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_sdk::move_types::language_storage::StructTag;
use aptos_transaction_builder::aptos_stdlib;
use aptos_types::account_address::AccountAddress;
use aptos_types::account_config::{AccountResource, CORE_CODE_ADDRESS};
use aptos_types::transaction::authenticator::AuthenticationKey;
use forge::Swarm;
use std::convert::TryFrom;
use std::str::FromStr;

use crate::smoke_test_environment::new_local_swarm_with_aptos;

#[tokio::test]
async fn test_get_index() {
    let mut swarm = new_local_swarm_with_aptos(1).await;
    let info = swarm.aptos_public_info();

    let resp = reqwest::get(info.url().to_owned()).await.unwrap();
    assert_eq!(reqwest::StatusCode::OK, resp.status());
}

#[tokio::test]
async fn test_basic_client() {
    let mut swarm = new_local_swarm_with_aptos(1).await;
    let mut info = swarm.aptos_public_info();

    info.client().get_ledger_information().await.unwrap();

    // TODO(Gas): double check if this is correct
    let mut account1 = info.create_and_fund_user_account(10_000).await.unwrap();
    // TODO(Gas): double check if this is correct
    let account2 = info.create_and_fund_user_account(10_000).await.unwrap();

    let tx = account1.sign_with_transaction_builder(
        info.transaction_factory()
            .payload(aptos_stdlib::aptos_coin_transfer(account2.address(), 1)),
    );
    let pending_txn = info.client().submit(&tx).await.unwrap().into_inner();

    info.client()
        .wait_for_transaction(&pending_txn)
        .await
        .unwrap();

    info.client()
        .get_transaction_by_hash(pending_txn.hash.into())
        .await
        .unwrap();

    info.client()
        .get_account_resources(CORE_CODE_ADDRESS)
        .await
        .unwrap();

    info.client().get_transactions(None, None).await.unwrap();
}

#[tokio::test]
async fn test_bcs() {
    let mut swarm = new_local_swarm_with_aptos(1).await;
    let mut info = swarm.aptos_public_info();

    // Create account
    let local_account = info.create_and_fund_user_account(10000000).await.unwrap();
    let account = local_account.address();
    let public_key = local_account.public_key();

    let client = info.client();
    // Check get account
    let account_resource = client.get_account_bcs(account).await.unwrap().into_inner();
    let expected_auth_key = AuthenticationKey::ed25519(public_key);
    let onchain_auth_key =
        AuthenticationKey::try_from(account_resource.authentication_key()).unwrap();
    assert_eq!(expected_auth_key, onchain_auth_key);
    assert_eq!(0, account_resource.sequence_number());

    // Check get resources
    let resources = client
        .get_account_resources_bcs(account)
        .await
        .unwrap()
        .into_inner();
    let bytes = resources
        .get(&StructTag::from_str("0x1::account::Account").unwrap())
        .unwrap();
    let account_resource: AccountResource = bcs::from_bytes(bytes).unwrap();
    assert_eq!(0, account_resource.sequence_number());

    // Check Modules align
    let modules = client
        .get_account_modules(AccountAddress::ONE)
        .await
        .unwrap()
        .into_inner();
    let bcs_modules = client
        .get_account_modules_bcs(AccountAddress::ONE)
        .await
        .unwrap()
        .into_inner();

    assert_eq!(modules.len(), bcs_modules.len());
    let (module_id, _) = modules.iter().next().unwrap();
    assert_eq!(
        &modules.get(module_id).unwrap().bytecode.0,
        bcs_modules.get(module_id).unwrap()
    );
}
<|endoftext|>


<commit_before>#![recursion_limit="128"]

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn poll_and_pending() {
    use futures::{pending, pin_mut, poll};
    use futures::executor::block_on;
    use futures::task::Poll;

    let pending_once = async { pending!() };
    block_on(async {
        pin_mut!(pending_once);
        assert_eq!(Poll::Pending, poll!(&mut pending_once));
        assert_eq!(Poll::Ready(()), poll!(&mut pending_once));
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn join() {
    use futures::{pin_mut, poll, join};
    use futures::channel::oneshot;
    use futures::executor::block_on;
    use futures::task::Poll;

    let (tx1, rx1) = oneshot::channel::<i32>();
    let (tx2, rx2) = oneshot::channel::<i32>();

    let fut = async {
        let res = join!(rx1, rx2);
        assert_eq!((Ok(1), Ok(2)), res);
    };

    block_on(async {
        pin_mut!(fut);
        assert_eq!(Poll::Pending, poll!(&mut fut));
        tx1.send(1).unwrap();
        assert_eq!(Poll::Pending, poll!(&mut fut));
        tx2.send(2).unwrap();
        assert_eq!(Poll::Ready(()), poll!(&mut fut));
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select() {
    use futures::select;
    use futures::channel::oneshot;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    let (tx1, rx1) = oneshot::channel::<i32>();
    let (_tx2, rx2) = oneshot::channel::<i32>();
    tx1.send(1).unwrap();
    let mut ran = false;
    block_on(async {
        select! {
            res = rx1.fuse() => {
                assert_eq!(Ok(1), res);
                ran = true;
            },
            _ = rx2.fuse() => unreachable!(),
        }
    });
    assert!(ran);
}

#[cfg(all(feature = "alloc", feature = "executor", feature = "async-await"))]
#[test]
fn select_biased() {
    use futures::channel::oneshot;
    use futures::executor::block_on;
    use futures::future::FutureExt;
    use futures::select_biased;

    let (tx1, rx1) = oneshot::channel::<i32>();
    let (_tx2, rx2) = oneshot::channel::<i32>();
    tx1.send(1).unwrap();
    let mut ran = false;
    block_on(async {
        select_biased! {
            res = rx1.fuse() => {
                assert_eq!(Ok(1), res);
                ran = true;
            },
            _ = rx2.fuse() => unreachable!(),
        }
    });
    assert!(ran);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_streams() {
    use futures::select;
    use futures::channel::mpsc;
    use futures::executor::block_on;
    use futures::sink::SinkExt;
    use futures::stream::StreamExt;

    let (mut tx1, rx1) = mpsc::channel::<i32>(1);
    let (mut tx2, rx2) = mpsc::channel::<i32>(1);
    let mut rx1 = rx1.fuse();
    let mut rx2 = rx2.fuse();
    let mut ran = false;
    let mut total = 0;
    block_on(async {
        let mut tx1_opt;
        let mut tx2_opt;
        select! {
            _ = rx1.next() => panic!(),
            _ = rx2.next() => panic!(),
            default => {
                tx1.send(2).await.unwrap();
                tx2.send(3).await.unwrap();
                tx1_opt = Some(tx1);
                tx2_opt = Some(tx2);
            }
            complete => panic!(),
        }
        loop {
            select! {
                // runs first and again after default
                x = rx1.next() => if let Some(x) = x { total += x; },
                // runs second and again after default
                x = rx2.next()  => if let Some(x) = x { total += x; },
                // runs third
                default => {
                    assert_eq!(total, 5);
                    ran = true;
                    drop(tx1_opt.take().unwrap());
                    drop(tx2_opt.take().unwrap());
                },
                // runs last
                complete => break,
            };
        }
    });
    assert!(ran);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_can_move_uncompleted_futures() {
    use futures::select;
    use futures::channel::oneshot;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    let (tx1, rx1) = oneshot::channel::<i32>();
    let (tx2, rx2) = oneshot::channel::<i32>();
    tx1.send(1).unwrap();
    tx2.send(2).unwrap();
    let mut ran = false;
    let mut rx1 = rx1.fuse();
    let mut rx2 = rx2.fuse();
    block_on(async {
        select! {
            res = rx1 => {
                assert_eq!(Ok(1), res);
                assert_eq!(Ok(2), rx2.await);
                ran = true;
            },
            res = rx2 => {
                assert_eq!(Ok(2), res);
                assert_eq!(Ok(1), rx1.await);
                ran = true;
            },
        }
    });
    assert!(ran);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_nested() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future;

    let mut outer_fut = future::ready(1);
    let mut inner_fut = future::ready(2);
    let res = block_on(async {
        select! {
            x = outer_fut => {
                select! {
                    y = inner_fut => x + y,
                }
            }
        }
    });
    assert_eq!(res, 3);
}

#[cfg(all(feature = "async-await", feature = "std"))]
#[test]
fn select_size() {
    use futures::select;
    use futures::future;

    let fut = async {
        let mut ready = future::ready(0i32);
        select! {
            _ = ready => {},
        }
    };
    assert_eq!(::std::mem::size_of_val(&fut), 24);

    let fut = async {
        let mut ready1 = future::ready(0i32);
        let mut ready2 = future::ready(0i32);
        select! {
            _ = ready1 => {},
            _ = ready2 => {},
        }
    };
    assert_eq!(::std::mem::size_of_val(&fut), 40);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_on_non_unpin_expressions() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    // The returned Future is !Unpin
    let make_non_unpin_fut = || { async {
        5
    }};

    let res = block_on(async {
        let select_res;
        select! {
            value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
            value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
        };
        select_res
    });
    assert_eq!(res, 5);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_on_non_unpin_expressions_with_default() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    // The returned Future is !Unpin
    let make_non_unpin_fut = || { async {
        5
    }};

    let res = block_on(async {
        let select_res;
        select! {
            value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
            value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
            default => { select_res = 7 },
        };
        select_res
    });
    assert_eq!(res, 5);
}

#[cfg(all(feature = "async-await", feature = "std"))]
#[test]
fn select_on_non_unpin_size() {
    use futures::select;
    use futures::future::FutureExt;

    // The returned Future is !Unpin
    let make_non_unpin_fut = || { async {
        5
    }};

    let fut = async {
        let select_res;
        select! {
            value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
            value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
        };
        select_res
    };

    assert_eq!(48, std::mem::size_of_val(&fut));
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_can_be_used_as_expression() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future;

    block_on(async {
        let res = select! {
            x = future::ready(7) => { x },
            y = future::ready(3) => { y + 1 },
        };
        assert!(res == 7 || res == 4);
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_with_default_can_be_used_as_expression() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::{FutureExt, poll_fn};
    use futures::task::{Context, Poll};

    fn poll_always_pending<T>(_cx: &mut Context<'_>) -> Poll<T> {
        Poll::Pending
    }

    block_on(async {
        let res = select! {
            x = poll_fn(poll_always_pending::<i32>).fuse() => x,
            y = poll_fn(poll_always_pending::<i32>).fuse() => { y + 1 },
            default => 99,
        };
        assert_eq!(res, 99);
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_with_complete_can_be_used_as_expression() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future;

    block_on(async {
        let res = select! {
            x = future::pending::<i32>() => { x },
            y = future::pending::<i32>() => { y + 1 },
            default => 99,
            complete => 237,
        };
        assert_eq!(res, 237);
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_on_mutable_borrowing_future_with_same_borrow_in_block() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    async fn require_mutable(_: &mut i32) {}
    async fn async_noop() {}

    block_on(async {
        let mut value = 234;
        select! {
            x = require_mutable(&mut value).fuse() => { },
            y = async_noop().fuse() => {
                value += 5;
            },
        }
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_on_mutable_borrowing_future_with_same_borrow_in_block_and_default() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    async fn require_mutable(_: &mut i32) {}
    async fn async_noop() {}

    block_on(async {
        let mut value = 234;
        select! {
            x = require_mutable(&mut value).fuse() => { },
            y = async_noop().fuse() => {
                value += 5;
            },
            default => {
                value += 27;
            },
        }
    });
}

#[cfg(feature = "async-await")]
#[test]
fn join_size() {
    use futures::join;
    use futures::future;

    let fut = async {
        let ready = future::ready(0i32);
        join!(ready)
    };
    assert_eq!(::std::mem::size_of_val(&fut), 16);

    let fut = async {
        let ready1 = future::ready(0i32);
        let ready2 = future::ready(0i32);
        join!(ready1, ready2)
    };
    assert_eq!(::std::mem::size_of_val(&fut), 28);
}

#[cfg(feature = "async-await")]
#[test]
fn try_join_size() {
    use futures::try_join;
    use futures::future;

    let fut = async {
        let ready = future::ready(Ok::<i32, i32>(0));
        try_join!(ready)
    };
    assert_eq!(::std::mem::size_of_val(&fut), 16);

    let fut = async {
        let ready1 = future::ready(Ok::<i32, i32>(0));
        let ready2 = future::ready(Ok::<i32, i32>(0));
        try_join!(ready1, ready2)
    };
    assert_eq!(::std::mem::size_of_val(&fut), 28);
}

#[cfg(feature = "async-await")]
#[test]
fn join_doesnt_require_unpin() {
    use futures::join;

    let _ = async {
        join!(async {}, async {})
    };
}

#[cfg(feature = "async-await")]
#[test]
fn try_join_doesnt_require_unpin() {
    use futures::try_join;

    let _ = async {
        try_join!(
            async { Ok::<(), ()>(()) },
            async { Ok::<(), ()>(()) },
        )
    };
}
<commit_msg>Update expected size of `select_on_non_unpin_size`<commit_after>#![recursion_limit="128"]

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn poll_and_pending() {
    use futures::{pending, pin_mut, poll};
    use futures::executor::block_on;
    use futures::task::Poll;

    let pending_once = async { pending!() };
    block_on(async {
        pin_mut!(pending_once);
        assert_eq!(Poll::Pending, poll!(&mut pending_once));
        assert_eq!(Poll::Ready(()), poll!(&mut pending_once));
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn join() {
    use futures::{pin_mut, poll, join};
    use futures::channel::oneshot;
    use futures::executor::block_on;
    use futures::task::Poll;

    let (tx1, rx1) = oneshot::channel::<i32>();
    let (tx2, rx2) = oneshot::channel::<i32>();

    let fut = async {
        let res = join!(rx1, rx2);
        assert_eq!((Ok(1), Ok(2)), res);
    };

    block_on(async {
        pin_mut!(fut);
        assert_eq!(Poll::Pending, poll!(&mut fut));
        tx1.send(1).unwrap();
        assert_eq!(Poll::Pending, poll!(&mut fut));
        tx2.send(2).unwrap();
        assert_eq!(Poll::Ready(()), poll!(&mut fut));
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select() {
    use futures::select;
    use futures::channel::oneshot;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    let (tx1, rx1) = oneshot::channel::<i32>();
    let (_tx2, rx2) = oneshot::channel::<i32>();
    tx1.send(1).unwrap();
    let mut ran = false;
    block_on(async {
        select! {
            res = rx1.fuse() => {
                assert_eq!(Ok(1), res);
                ran = true;
            },
            _ = rx2.fuse() => unreachable!(),
        }
    });
    assert!(ran);
}

#[cfg(all(feature = "alloc", feature = "executor", feature = "async-await"))]
#[test]
fn select_biased() {
    use futures::channel::oneshot;
    use futures::executor::block_on;
    use futures::future::FutureExt;
    use futures::select_biased;

    let (tx1, rx1) = oneshot::channel::<i32>();
    let (_tx2, rx2) = oneshot::channel::<i32>();
    tx1.send(1).unwrap();
    let mut ran = false;
    block_on(async {
        select_biased! {
            res = rx1.fuse() => {
                assert_eq!(Ok(1), res);
                ran = true;
            },
            _ = rx2.fuse() => unreachable!(),
        }
    });
    assert!(ran);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_streams() {
    use futures::select;
    use futures::channel::mpsc;
    use futures::executor::block_on;
    use futures::sink::SinkExt;
    use futures::stream::StreamExt;

    let (mut tx1, rx1) = mpsc::channel::<i32>(1);
    let (mut tx2, rx2) = mpsc::channel::<i32>(1);
    let mut rx1 = rx1.fuse();
    let mut rx2 = rx2.fuse();
    let mut ran = false;
    let mut total = 0;
    block_on(async {
        let mut tx1_opt;
        let mut tx2_opt;
        select! {
            _ = rx1.next() => panic!(),
            _ = rx2.next() => panic!(),
            default => {
                tx1.send(2).await.unwrap();
                tx2.send(3).await.unwrap();
                tx1_opt = Some(tx1);
                tx2_opt = Some(tx2);
            }
            complete => panic!(),
        }
        loop {
            select! {
                // runs first and again after default
                x = rx1.next() => if let Some(x) = x { total += x; },
                // runs second and again after default
                x = rx2.next()  => if let Some(x) = x { total += x; },
                // runs third
                default => {
                    assert_eq!(total, 5);
                    ran = true;
                    drop(tx1_opt.take().unwrap());
                    drop(tx2_opt.take().unwrap());
                },
                // runs last
                complete => break,
            };
        }
    });
    assert!(ran);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_can_move_uncompleted_futures() {
    use futures::select;
    use futures::channel::oneshot;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    let (tx1, rx1) = oneshot::channel::<i32>();
    let (tx2, rx2) = oneshot::channel::<i32>();
    tx1.send(1).unwrap();
    tx2.send(2).unwrap();
    let mut ran = false;
    let mut rx1 = rx1.fuse();
    let mut rx2 = rx2.fuse();
    block_on(async {
        select! {
            res = rx1 => {
                assert_eq!(Ok(1), res);
                assert_eq!(Ok(2), rx2.await);
                ran = true;
            },
            res = rx2 => {
                assert_eq!(Ok(2), res);
                assert_eq!(Ok(1), rx1.await);
                ran = true;
            },
        }
    });
    assert!(ran);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_nested() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future;

    let mut outer_fut = future::ready(1);
    let mut inner_fut = future::ready(2);
    let res = block_on(async {
        select! {
            x = outer_fut => {
                select! {
                    y = inner_fut => x + y,
                }
            }
        }
    });
    assert_eq!(res, 3);
}

#[cfg(all(feature = "async-await", feature = "std"))]
#[test]
fn select_size() {
    use futures::select;
    use futures::future;

    let fut = async {
        let mut ready = future::ready(0i32);
        select! {
            _ = ready => {},
        }
    };
    assert_eq!(::std::mem::size_of_val(&fut), 24);

    let fut = async {
        let mut ready1 = future::ready(0i32);
        let mut ready2 = future::ready(0i32);
        select! {
            _ = ready1 => {},
            _ = ready2 => {},
        }
    };
    assert_eq!(::std::mem::size_of_val(&fut), 40);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_on_non_unpin_expressions() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    // The returned Future is !Unpin
    let make_non_unpin_fut = || { async {
        5
    }};

    let res = block_on(async {
        let select_res;
        select! {
            value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
            value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
        };
        select_res
    });
    assert_eq!(res, 5);
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_on_non_unpin_expressions_with_default() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    // The returned Future is !Unpin
    let make_non_unpin_fut = || { async {
        5
    }};

    let res = block_on(async {
        let select_res;
        select! {
            value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
            value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
            default => { select_res = 7 },
        };
        select_res
    });
    assert_eq!(res, 5);
}

#[cfg(all(feature = "async-await", feature = "std"))]
#[test]
fn select_on_non_unpin_size() {
    use futures::select;
    use futures::future::FutureExt;

    // The returned Future is !Unpin
    let make_non_unpin_fut = || { async {
        5
    }};

    let fut = async {
        let select_res;
        select! {
            value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
            value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
        };
        select_res
    };

    assert_eq!(32, std::mem::size_of_val(&fut));
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_can_be_used_as_expression() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future;

    block_on(async {
        let res = select! {
            x = future::ready(7) => { x },
            y = future::ready(3) => { y + 1 },
        };
        assert!(res == 7 || res == 4);
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_with_default_can_be_used_as_expression() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::{FutureExt, poll_fn};
    use futures::task::{Context, Poll};

    fn poll_always_pending<T>(_cx: &mut Context<'_>) -> Poll<T> {
        Poll::Pending
    }

    block_on(async {
        let res = select! {
            x = poll_fn(poll_always_pending::<i32>).fuse() => x,
            y = poll_fn(poll_always_pending::<i32>).fuse() => { y + 1 },
            default => 99,
        };
        assert_eq!(res, 99);
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_with_complete_can_be_used_as_expression() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future;

    block_on(async {
        let res = select! {
            x = future::pending::<i32>() => { x },
            y = future::pending::<i32>() => { y + 1 },
            default => 99,
            complete => 237,
        };
        assert_eq!(res, 237);
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_on_mutable_borrowing_future_with_same_borrow_in_block() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    async fn require_mutable(_: &mut i32) {}
    async fn async_noop() {}

    block_on(async {
        let mut value = 234;
        select! {
            x = require_mutable(&mut value).fuse() => { },
            y = async_noop().fuse() => {
                value += 5;
            },
        }
    });
}

#[cfg(all(feature = "async-await", feature = "std", feature = "executor"))]
#[test]
fn select_on_mutable_borrowing_future_with_same_borrow_in_block_and_default() {
    use futures::select;
    use futures::executor::block_on;
    use futures::future::FutureExt;

    async fn require_mutable(_: &mut i32) {}
    async fn async_noop() {}

    block_on(async {
        let mut value = 234;
        select! {
            x = require_mutable(&mut value).fuse() => { },
            y = async_noop().fuse() => {
                value += 5;
            },
            default => {
                value += 27;
            },
        }
    });
}

#[cfg(feature = "async-await")]
#[test]
fn join_size() {
    use futures::join;
    use futures::future;

    let fut = async {
        let ready = future::ready(0i32);
        join!(ready)
    };
    assert_eq!(::std::mem::size_of_val(&fut), 16);

    let fut = async {
        let ready1 = future::ready(0i32);
        let ready2 = future::ready(0i32);
        join!(ready1, ready2)
    };
    assert_eq!(::std::mem::size_of_val(&fut), 28);
}

#[cfg(feature = "async-await")]
#[test]
fn try_join_size() {
    use futures::try_join;
    use futures::future;

    let fut = async {
        let ready = future::ready(Ok::<i32, i32>(0));
        try_join!(ready)
    };
    assert_eq!(::std::mem::size_of_val(&fut), 16);

    let fut = async {
        let ready1 = future::ready(Ok::<i32, i32>(0));
        let ready2 = future::ready(Ok::<i32, i32>(0));
        try_join!(ready1, ready2)
    };
    assert_eq!(::std::mem::size_of_val(&fut), 28);
}

#[cfg(feature = "async-await")]
#[test]
fn join_doesnt_require_unpin() {
    use futures::join;

    let _ = async {
        join!(async {}, async {})
    };
}

#[cfg(feature = "async-await")]
#[test]
fn try_join_doesnt_require_unpin() {
    use futures::try_join;

    let _ = async {
        try_join!(
            async { Ok::<(), ()>(()) },
            async { Ok::<(), ()>(()) },
        )
    };
}
<|endoftext|>