<commit_before>//! When *constructing* `hir`, we start at some parent syntax node and recursively
//! lower the children.
//!
//! This modules allows one to go in the opposite direction: start with a syntax
//! node for a *child*, and get its hir.

use either::Either;
use hir_expand::HirFileId;
use syntax::ast::HasDocComments;

use crate::{
    db::DefDatabase,
    dyn_map::DynMap,
    item_scope::ItemScope,
    keys,
    src::{HasChildSource, HasSource},
    AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, ModuleDefId,
    ModuleId, TraitId, VariantId,
};

pub trait ChildBySource {
    fn child_by_source(&self, db: &dyn DefDatabase, file_id: HirFileId) -> DynMap {
        let mut res = DynMap::default();
        self.child_by_source_to(db, &mut res, file_id);
        res
    }
    fn child_by_source_to(&self, db: &dyn DefDatabase, map: &mut DynMap, file_id: HirFileId);
}

impl ChildBySource for TraitId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        let data = db.trait_data(*self);
        // FIXME attribute macros
        for (_name, item) in data.items.iter() {
            match *item {
                AssocItemId::FunctionId(func) => {
                    let loc = func.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        res[keys::FUNCTION].insert(src, func)
                    }
                }
                AssocItemId::ConstId(konst) => {
                    let loc = konst.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        res[keys::CONST].insert(src, konst)
                    }
                }
                AssocItemId::TypeAliasId(ty) => {
                    let loc = ty.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        res[keys::TYPE_ALIAS].insert(src, ty)
                    }
                }
            }
        }
    }
}

impl ChildBySource for ImplId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        let data = db.impl_data(*self);
        // FIXME attribute macros
        for &item in data.items.iter() {
            match item {
                AssocItemId::FunctionId(func) => {
                    let loc = func.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        res[keys::FUNCTION].insert(src, func)
                    }
                }
                AssocItemId::ConstId(konst) => {
                    let loc = konst.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        res[keys::CONST].insert(src, konst)
                    }
                }
                AssocItemId::TypeAliasId(ty) => {
                    let loc = ty.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        res[keys::TYPE_ALIAS].insert(src, ty)
                    }
                }
            }
        }
    }
}

impl ChildBySource for ModuleId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        let def_map = self.def_map(db);
        let module_data = &def_map[self.local_id];
        module_data.scope.child_by_source_to(db, res, file_id);
    }
}

impl ChildBySource for ItemScope {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        self.declarations().for_each(|item| add_module_def(db, file_id, res, item));
        self.macros().for_each(|(_, makro)| {
            let ast_id = makro.ast_id();
            if ast_id.either(|it| it.file_id, |it| it.file_id) == file_id {
                let src = match ast_id {
                    Either::Left(ast_id) => ast_id.with_value(ast_id.to_node(db.upcast())),
                    // FIXME: Do we need to add proc-macros into a PROCMACRO dynmap here?
                    Either::Right(_fn) => return,
                };
                res[keys::MACRO_CALL].insert(src, makro);
            }
        });
        self.unnamed_consts().for_each(|konst| {
            let loc = konst.lookup(db);
            if loc.id.file_id() == file_id {
                let src = loc.source(db);
                res[keys::CONST].insert(src, konst);
            }
        });
        self.impls().for_each(|imp| add_impl(db, file_id, res, imp));
        self.attr_macro_invocs().for_each(|(ast_id, call_id)| {
            if ast_id.file_id == file_id {
                let item = ast_id.with_value(ast_id.to_node(db.upcast()));
                res[keys::ATTR_MACRO_CALL].insert(item, call_id);
            }
        });
        self.derive_macro_invocs().for_each(|(ast_id, calls)| {
            if ast_id.file_id != file_id {
                return;
            }
            let adt = ast_id.to_node(db.upcast());
            for (attr_id, calls) in calls {
                if let Some(Either::Right(attr)) =
                    adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
                {
                    res[keys::DERIVE_MACRO_CALL]
                        .insert(ast_id.with_value(attr), (attr_id, calls.into()));
                }
            }
        });

        fn add_module_def(
            db: &dyn DefDatabase,
            file_id: HirFileId,
            map: &mut DynMap,
            item: ModuleDefId,
        ) {
            match item {
                ModuleDefId::FunctionId(func) => {
                    let loc = func.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::FUNCTION].insert(src, func)
                    }
                }
                ModuleDefId::ConstId(konst) => {
                    let loc = konst.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::CONST].insert(src, konst)
                    }
                }
                ModuleDefId::StaticId(statik) => {
                    let loc = statik.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::STATIC].insert(src, statik)
                    }
                }
                ModuleDefId::TypeAliasId(ty) => {
                    let loc = ty.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::TYPE_ALIAS].insert(src, ty)
                    }
                }
                ModuleDefId::TraitId(trait_) => {
                    let loc = trait_.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::TRAIT].insert(src, trait_)
                    }
                }
                ModuleDefId::AdtId(adt) => match adt {
                    AdtId::StructId(strukt) => {
                        let loc = strukt.lookup(db);
                        if loc.id.file_id() == file_id {
                            let src = loc.source(db);
                            map[keys::STRUCT].insert(src, strukt)
                        }
                    }
                    AdtId::UnionId(union_) => {
                        let loc = union_.lookup(db);
                        if loc.id.file_id() == file_id {
                            let src = loc.source(db);
                            map[keys::UNION].insert(src, union_)
                        }
                    }
                    AdtId::EnumId(enum_) => {
                        let loc = enum_.lookup(db);
                        if loc.id.file_id() == file_id {
                            let src = loc.source(db);
                            map[keys::ENUM].insert(src, enum_)
                        }
                    }
                },
                _ => (),
            }
        }
        fn add_impl(db: &dyn DefDatabase, file_id: HirFileId, map: &mut DynMap, imp: ImplId) {
            let loc = imp.lookup(db);
            if loc.id.file_id() == file_id {
                let src = loc.source(db);
                map[keys::IMPL].insert(src, imp)
            }
        }
    }
}

impl ChildBySource for VariantId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
        let arena_map = self.child_source(db);
        let arena_map = arena_map.as_ref();
        let parent = *self;
        for (local_id, source) in arena_map.value.iter() {
            let id = FieldId { parent, local_id };
            match source.clone() {
                Either::Left(source) => {
                    res[keys::TUPLE_FIELD].insert(arena_map.with_value(source), id)
                }
                Either::Right(source) => {
                    res[keys::RECORD_FIELD].insert(arena_map.with_value(source), id)
                }
            }
        }
    }
}

impl ChildBySource for EnumId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
        let arena_map = self.child_source(db);
        let arena_map = arena_map.as_ref();
        for (local_id, source) in arena_map.value.iter() {
            let id = EnumVariantId { parent: *self, local_id };
            res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id)
        }
    }
}

impl ChildBySource for DefWithBodyId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        let body = db.body(*self);
        for (_, def_map) in body.blocks(db) {
            // All block expressions are merged into the same map, because they logically all add
            // inner items to the containing `DefWithBodyId`.
            def_map[def_map.root()].scope.child_by_source_to(db, res, file_id);
        }
    }
}
<commit_msg>Simplify<commit_after>//! When *constructing* `hir`, we start at some parent syntax node and recursively
//! lower the children.
//!
//! This modules allows one to go in the opposite direction: start with a syntax
//! node for a *child*, and get its hir.

use either::Either;
use hir_expand::HirFileId;
use syntax::ast::HasDocComments;

use crate::{
    db::DefDatabase,
    dyn_map::DynMap,
    item_scope::ItemScope,
    keys,
    src::{HasChildSource, HasSource},
    AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, ModuleDefId,
    ModuleId, TraitId, VariantId,
};

pub trait ChildBySource {
    fn child_by_source(&self, db: &dyn DefDatabase, file_id: HirFileId) -> DynMap {
        let mut res = DynMap::default();
        self.child_by_source_to(db, &mut res, file_id);
        res
    }
    fn child_by_source_to(&self, db: &dyn DefDatabase, map: &mut DynMap, file_id: HirFileId);
}

impl ChildBySource for TraitId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        let data = db.trait_data(*self);
        // FIXME attribute macros
        for &(_, item) in data.items.iter() {
            child_by_source_assoc_items(db, res, file_id, item);
        }
    }
}

impl ChildBySource for ImplId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        let data = db.impl_data(*self);
        // FIXME attribute macros
        for &item in data.items.iter() {
            child_by_source_assoc_items(db, res, file_id, item);
        }
    }
}

fn child_by_source_assoc_items(
    db: &dyn DefDatabase,
    res: &mut DynMap,
    file_id: HirFileId,
    item: AssocItemId,
) {
    match item {
        AssocItemId::FunctionId(func) => {
            let loc = func.lookup(db);
            if loc.id.file_id() == file_id {
                let src = loc.source(db);
                res[keys::FUNCTION].insert(src, func)
            }
        }
        AssocItemId::ConstId(konst) => {
            let loc = konst.lookup(db);
            if loc.id.file_id() == file_id {
                let src = loc.source(db);
                res[keys::CONST].insert(src, konst)
            }
        }
        AssocItemId::TypeAliasId(ty) => {
            let loc = ty.lookup(db);
            if loc.id.file_id() == file_id {
                let src = loc.source(db);
                res[keys::TYPE_ALIAS].insert(src, ty)
            }
        }
    }
}

impl ChildBySource for ModuleId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        let def_map = self.def_map(db);
        let module_data = &def_map[self.local_id];
        module_data.scope.child_by_source_to(db, res, file_id);
    }
}

impl ChildBySource for ItemScope {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        self.declarations().for_each(|item| add_module_def(db, file_id, res, item));
        self.macros().for_each(|(_, makro)| {
            let ast_id = makro.ast_id();
            if ast_id.either(|it| it.file_id, |it| it.file_id) == file_id {
                let src = match ast_id {
                    Either::Left(ast_id) => ast_id.with_value(ast_id.to_node(db.upcast())),
                    // FIXME: Do we need to add proc-macros into a PROCMACRO dynmap here?
                    Either::Right(_fn) => return,
                };
                res[keys::MACRO_CALL].insert(src, makro);
            }
        });
        self.unnamed_consts().for_each(|konst| {
            let loc = konst.lookup(db);
            if loc.id.file_id() == file_id {
                let src = loc.source(db);
                res[keys::CONST].insert(src, konst);
            }
        });
        self.impls().for_each(|imp| add_impl(db, file_id, res, imp));
        self.attr_macro_invocs().for_each(|(ast_id, call_id)| {
            if ast_id.file_id == file_id {
                let item = ast_id.with_value(ast_id.to_node(db.upcast()));
                res[keys::ATTR_MACRO_CALL].insert(item, call_id);
            }
        });
        self.derive_macro_invocs().for_each(|(ast_id, calls)| {
            if ast_id.file_id != file_id {
                return;
            }
            let adt = ast_id.to_node(db.upcast());
            for (attr_id, calls) in calls {
                if let Some(Either::Right(attr)) =
                    adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
                {
                    res[keys::DERIVE_MACRO_CALL]
                        .insert(ast_id.with_value(attr), (attr_id, calls.into()));
                }
            }
        });

        fn add_module_def(
            db: &dyn DefDatabase,
            file_id: HirFileId,
            map: &mut DynMap,
            item: ModuleDefId,
        ) {
            match item {
                ModuleDefId::FunctionId(func) => {
                    let loc = func.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::FUNCTION].insert(src, func)
                    }
                }
                ModuleDefId::ConstId(konst) => {
                    let loc = konst.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::CONST].insert(src, konst)
                    }
                }
                ModuleDefId::StaticId(statik) => {
                    let loc = statik.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::STATIC].insert(src, statik)
                    }
                }
                ModuleDefId::TypeAliasId(ty) => {
                    let loc = ty.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::TYPE_ALIAS].insert(src, ty)
                    }
                }
                ModuleDefId::TraitId(trait_) => {
                    let loc = trait_.lookup(db);
                    if loc.id.file_id() == file_id {
                        let src = loc.source(db);
                        map[keys::TRAIT].insert(src, trait_)
                    }
                }
                ModuleDefId::AdtId(adt) => match adt {
                    AdtId::StructId(strukt) => {
                        let loc = strukt.lookup(db);
                        if loc.id.file_id() == file_id {
                            let src = loc.source(db);
                            map[keys::STRUCT].insert(src, strukt)
                        }
                    }
                    AdtId::UnionId(union_) => {
                        let loc = union_.lookup(db);
                        if loc.id.file_id() == file_id {
                            let src = loc.source(db);
                            map[keys::UNION].insert(src, union_)
                        }
                    }
                    AdtId::EnumId(enum_) => {
                        let loc = enum_.lookup(db);
                        if loc.id.file_id() == file_id {
                            let src = loc.source(db);
                            map[keys::ENUM].insert(src, enum_)
                        }
                    }
                },
                _ => (),
            }
        }
        fn add_impl(db: &dyn DefDatabase, file_id: HirFileId, map: &mut DynMap, imp: ImplId) {
            let loc = imp.lookup(db);
            if loc.id.file_id() == file_id {
                let src = loc.source(db);
                map[keys::IMPL].insert(src, imp)
            }
        }
    }
}

impl ChildBySource for VariantId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
        let arena_map = self.child_source(db);
        let arena_map = arena_map.as_ref();
        let parent = *self;
        for (local_id, source) in arena_map.value.iter() {
            let id = FieldId { parent, local_id };
            match source.clone() {
                Either::Left(source) => {
                    res[keys::TUPLE_FIELD].insert(arena_map.with_value(source), id)
                }
                Either::Right(source) => {
                    res[keys::RECORD_FIELD].insert(arena_map.with_value(source), id)
                }
            }
        }
    }
}

impl ChildBySource for EnumId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, _: HirFileId) {
        let arena_map = self.child_source(db);
        let arena_map = arena_map.as_ref();
        for (local_id, source) in arena_map.value.iter() {
            let id = EnumVariantId { parent: *self, local_id };
            res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id)
        }
    }
}

impl ChildBySource for DefWithBodyId {
    fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
        let body = db.body(*self);
        for (_, def_map) in body.blocks(db) {
            // All block expressions are merged into the same map, because they logically all add
            // inner items to the containing `DefWithBodyId`.
            def_map[def_map.root()].scope.child_by_source_to(db, res, file_id);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]
#![deny(print_with_newline)]

fn main() {
    print!("Hello\n"); //~ERROR using `print!()` with a format string
    print!("Hello {}\n", "world"); //~ERROR using `print!()` with a format string
    print!("Hello {} {}\n\n", "world", "#2"); //~ERROR using `print!()` with a format string
    print!("{}\n", 1265); //~ERROR using `print!()` with a format string

    // these are all fine
    print!("");
    print!("Hello");
    println!("Hello");
    println!("Hello\n");
    println!("Hello {}\n", "world");
    print!("Issue\n{}", 1265);
    print!("{}", 1265);
}
<commit_msg>Test for #1275<commit_after>#![feature(plugin)]
#![plugin(clippy)]
#![deny(print_with_newline)]

fn main() {
    print!("Hello\n"); //~ERROR using `print!()` with a format string
    print!("Hello {}\n", "world"); //~ERROR using `print!()` with a format string
    print!("Hello {} {}\n\n", "world", "#2"); //~ERROR using `print!()` with a format string
    print!("{}\n", 1265); //~ERROR using `print!()` with a format string

    // these are all fine
    print!("");
    print!("Hello");
    println!("Hello");
    println!("Hello\n");
    println!("Hello {}\n", "world");
    print!("Issue\n{}", 1265);
    print!("{}", 1265);
    print!("\n{}", 1275);
}
<|endoftext|>


<commit_before>#[allow(unused_imports)]
use mysql_async::{
    chrono, consts, error, from_row, from_row_opt, from_value, from_value_opt,
    futures::{DisconnectPool, GetConn},
    params,
    prelude::{
        ConnectionLike, ConvIr, FromRow, FromValue, LocalInfileHandler, Protocol, Queryable,
        ToValue,
    },
    time, uuid, BinaryProtocol, BoxFuture, Column, Conn, Deserialized, FromRowError,
    FromValueError, IsolationLevel, Opts, OptsBuilder, Params, Pool, PoolConstraints, QueryResult,
    Row, Serialized, SslOpts, Stmt, TextProtocol, Transaction, TransactionOptions, Value,
    WhiteListFsLocalInfileHandler,
};
<commit_msg>Extend the exports test<commit_after>#[allow(unused_imports)]
use mysql_async::{
    chrono, consts, error, from_row, from_row_opt, from_value, from_value_opt,
    futures::{DisconnectPool, GetConn},
    params,
    prelude::{
        ConnectionLike, ConvIr, FromRow, FromValue, LocalInfileHandler, Protocol, Queryable,
        ToValue,
    },
    time, uuid, BinaryProtocol, BoxFuture, Column, Conn, Deserialized, FromRowError,
    FromValueError, IsolationLevel, Opts, OptsBuilder, Params, Pool, PoolConstraints, PoolOptions,
    QueryResult, Row, Serialized, SslOpts, Stmt, TextProtocol, Transaction, TransactionOptions,
    Value, WhiteListFsLocalInfileHandler, DEFAULT_INACTIVE_CONNECTION_TTL,
    DEFAULT_TTL_CHECK_INTERVAL,
};
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

#![feature(fs_walk)]
#![feature(path_ext)]
#![feature(slice_patterns)]
#![feature(test)]

#[macro_use] extern crate bitflags;
extern crate png;
extern crate test;
extern crate url;
extern crate util;

use std::env;
use std::ffi::OsStr;
use std::fs::{PathExt, File, walk_dir};
use std::io::{self, Read, Result};
use std::path::{Path, PathBuf};
use std::process;
use std::process::{Command, Stdio};
use std::thread::sleep_ms;
use test::run_tests_console;
use test::{AutoColor, DynTestName, DynTestFn, TestDesc, TestOpts, TestDescAndFn, ShouldPanic};
use url::Url;

bitflags!(
    flags RenderMode: u32 {
        const CPU_RENDERING  = 0x00000001,
        const GPU_RENDERING  = 0x00000010,
        const LINUX_TARGET   = 0x00000100,
        const MACOS_TARGET   = 0x00001000,
        const ANDROID_TARGET = 0x00010000
    }
);

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut parts = args[1..].split(|e| &**e == "--");

    let harness_args = parts.next().unwrap();  // .split() is never empty
    let servo_args = parts.next().unwrap_or(&[]);

    let (render_mode_string, base_path, testnames) = match harness_args {
        [ref render_mode_string, ref base_path, testnames..] =>
            (render_mode_string, base_path, testnames),
        _ => panic!("USAGE: cpu|gpu base_path [testname ...]"),
    };

    let mut render_mode = match &**render_mode_string {
        "cpu" => CPU_RENDERING,
        "gpu" => GPU_RENDERING,
        _ => panic!("First argument must specify cpu or gpu as rendering mode")
    };
    if cfg!(target_os = "linux") {
        render_mode.insert(LINUX_TARGET);
    }
    if cfg!(target_os = "macos") {
        render_mode.insert(MACOS_TARGET);
    }
    if cfg!(target_os = "android") {
        render_mode.insert(ANDROID_TARGET);
    }

    let mut all_tests = vec!();
    println!("Scanning {} for manifests\n", base_path);

    for file in walk_dir(base_path).unwrap() {
        let file = file.unwrap().path();
        let maybe_extension = file.extension();
        match maybe_extension {
            Some(extension) => {
                if extension == OsStr::new("list") && file.is_file() {
                    let len = all_tests.len();
                    let mut tests = parse_lists(&file, testnames, servo_args, render_mode, len);
                    println!("\t{} [{} tests]", file.display(), tests.len());
                    all_tests.append(&mut tests);
                }
            }
            _ => {}
        }
    }

    let test_opts = TestOpts {
        filter: None,
        run_ignored: false,
        logfile: None,
        run_tests: true,
        bench_benchmarks: false,
        nocapture: false,
        color: AutoColor,
    };

    match run(test_opts,
              all_tests,
              servo_args.iter().map(|x| x.clone()).collect()) {
        Ok(false) => process::exit(1), // tests failed
        Err(_) => process::exit(2),    // I/O-related failure
        _ => (),
    }
}

fn run(test_opts: TestOpts, all_tests: Vec<TestDescAndFn>,
       servo_args: Vec<String>) -> io::Result<bool> {
    // Verify that we're passing in valid servo arguments. Otherwise, servo
    // will exit before we've run any tests, and it will appear to us as if
    // all the tests are failing.
    let mut command = Command::new(&servo_path());
    command
        .args(&servo_args)
        .arg("-z")
        .arg("about:blank");

    let mut child = match command.spawn() {
        Ok(p) => p,
        Err(e) => panic!("failed to execute process: {}", e),
    };

    // Wait for the shell to launch or to fail
    sleep_ms(1000);
    child.kill().unwrap();
    let output = try!(child.wait_with_output());

    let stderr = String::from_utf8(output.stderr).unwrap();

    if stderr.contains("Unrecognized") {
        println!("Servo: {}", stderr);
        return Ok(false);
    }

    run_tests_console(&test_opts, all_tests)
}

#[derive(PartialEq)]
enum ReftestKind {
    Same,
    Different,
}

struct Reftest {
    name: String,
    kind: ReftestKind,
    files: [PathBuf; 2],
    id: usize,
    servo_args: Vec<String>,
    render_mode: RenderMode,
    is_flaky: bool,
    prefs: Vec<String>,
    fragment_identifier: Option<String>,
    resolution: Option<String>,
    pixel_ratio: Option<f32>,
}

struct TestLine<'a> {
    conditions: &'a str,
    kind: &'a str,
    file_left: &'a str,
    file_right: &'a str,
}

fn parse_lists(file: &Path,
               filters: &[String],
               servo_args: &[String],
               render_mode: RenderMode,
               id_offset: usize)
               -> Vec<TestDescAndFn> {
    let mut tests = Vec::new();
    let contents = {
        let mut f = File::open(file).unwrap();
        let mut contents = String::new();
        f.read_to_string(&mut contents).unwrap();
        contents
    };

    for line in contents.lines() {
        // ignore comments or empty lines
        if line.starts_with("#") || line.is_empty() {
            continue;
        }

        let parts: Vec<&str> = line.split(' ').filter(|p| !p.is_empty()).collect();

        let test_line = match parts.len() {
            3 => TestLine {
                conditions: "",
                kind: parts[0],
                file_left: parts[1],
                file_right: parts[2],
            },
            4 => TestLine {
                conditions: parts[0],
                kind: parts[1],
                file_left: parts[2],
                file_right: parts[3],
            },
            _ => panic!("reftest line: '{}' doesn't match '[CONDITIONS] KIND LEFT RIGHT'", line),
        };

        let kind = match test_line.kind {
            "==" => ReftestKind::Same,
            "!=" => ReftestKind::Different,
            part => panic!("reftest line: '{}' has invalid kind '{}'", line, part)
        };

        let base = env::current_dir().unwrap().join(file.parent().unwrap());

        let file_left =  base.join(test_line.file_left);
        let file_right = base.join(test_line.file_right);

        let conditions_list = test_line.conditions.split(',');
        let mut flakiness = RenderMode::empty();
        let mut prefs = vec![];
        let mut fragment_identifier = None;
        let mut resolution = None;
        let mut pixel_ratio = None;
        for condition in conditions_list {
            match condition {
                "flaky_cpu" => flakiness.insert(CPU_RENDERING),
                "flaky_gpu" => flakiness.insert(GPU_RENDERING),
                "flaky_linux" => flakiness.insert(LINUX_TARGET),
                "flaky_macos" => flakiness.insert(MACOS_TARGET),
                _ => ()
            }
            if condition.starts_with("prefs:\"") {
                if let Some(joined) = condition.split("\"").nth(1) {
                    prefs.extend(joined.split(",").map(str::to_owned));
                }
            }
            if condition.starts_with("fragment=") {
                fragment_identifier = Some(condition["fragment=".len()..].to_string());
            }
            if condition.starts_with("resolution=") {
                resolution = Some(condition["resolution=".len() ..].to_string());
            }
            if condition.starts_with("device-pixel-ratio=") {
                pixel_ratio = Some(condition["device-pixel-ratio=".len() ..].to_string()
                                   .parse().expect("Invalid device-pixel-ratio"));
            }
        }

        let reftest = Reftest {
            name: format!("{} {} {}", test_line.file_left, test_line.kind, test_line.file_right),
            kind: kind,
            files: [file_left, file_right],
            id: id_offset + tests.len(),
            render_mode: render_mode,
            servo_args: servo_args.to_vec(),
            is_flaky: render_mode.intersects(flakiness),
            prefs: prefs,
            fragment_identifier: fragment_identifier,
            resolution: resolution,
            pixel_ratio: pixel_ratio,
        };

        if filters.is_empty() || filters.iter().any(|pattern| reftest.name.contains(pattern)) {
            tests.push(make_test(reftest));
        }
    }
    tests
}

fn make_test(reftest: Reftest) -> TestDescAndFn {
    let name = reftest.name.clone();
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(name),
            ignore: false,
            should_panic: ShouldPanic::No,
        },
        testfn: DynTestFn(Box::new(move || {
            check_reftest(reftest);
        })),
    }
}

fn capture(reftest: &Reftest, side: usize) -> (u32, u32, Vec<u8>) {
    let png_filename = format!("/tmp/servo-reftest-{:06}-{}.png", reftest.id, side);
    let mut command = Command::new(&servo_path());
    command
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .args(&reftest.servo_args[..])
        .arg("--user-stylesheet").arg(util::resource_files::resources_dir_path().join("ahem.css"))
        // Allows pixel perfect rendering of Ahem font and the HTML canvas for reftests.
        .arg("-Z")
        .arg("disable-text-aa,disable-canvas-aa")
        .args(&["-f", "-o"])
        .arg(&png_filename)
        .arg(&{
            let mut url = Url::from_file_path(&*reftest.files[side]).unwrap();
            url.fragment = reftest.fragment_identifier.clone();
            url.to_string()
        });
    // CPU rendering is the default
    if reftest.render_mode.contains(CPU_RENDERING) {
        command.arg("-c");
    }
    if reftest.render_mode.contains(GPU_RENDERING) {
        command.arg("-g");
    }
    for pref in &reftest.prefs {
        command.arg("--pref");
        command.arg(pref);
    }
    if let Some(ref resolution) = reftest.resolution {
        command.arg("--resolution");
        command.arg(resolution);
    }
    if let Some(pixel_ratio) = reftest.pixel_ratio {
        command.arg("--device-pixel-ratio");
        command.arg(pixel_ratio.to_string());
    }
    let retval = match command.status() {
        Ok(status) => status,
        Err(e) => panic!("failed to execute process: {}", e),
    };
    assert!(retval.success());

    let image = png::load_png(&png_filename).unwrap();
    let rgba8_bytes = match image.pixels {
        png::PixelsByColorType::RGBA8(pixels) => pixels,
        _ => panic!(),
    };
    (image.width, image.height, rgba8_bytes)
}

fn servo_path() -> PathBuf {
    let current_exe = env::current_exe().ok().expect("Could not locate current executable");
    current_exe.parent().unwrap().join("servo")
}

fn check_reftest(reftest: Reftest) {
    let (left_width, left_height, left_bytes) = capture(&reftest, 0);
    let (right_width, right_height, right_bytes) = capture(&reftest, 1);

    assert_eq!(left_width, right_width);
    assert_eq!(left_height, right_height);

    let left_all_white = left_bytes.iter().all(|&p| p == 255);
    let right_all_white = right_bytes.iter().all(|&p| p == 255);

    if left_all_white && right_all_white {
        panic!("Both renderings are empty")
    }

    let pixels = left_bytes.iter().zip(right_bytes.iter()).map(|(&a, &b)| {
        if a == b {
            // White for correct
            0xFF
        } else {
            // "1100" in the RGBA channel with an error for an incorrect value
            // This results in some number of C0 and FFs, which is much more
            // readable (and distinguishable) than the previous difference-wise
            // scaling but does not require reconstructing the actual RGBA pixel.
            0xC0
        }
    }).collect::<Vec<u8>>();

    if pixels.iter().any(|&a| a < 255) {
        let output = format!("/tmp/servo-reftest-{:06}-diff.png", reftest.id);

        let mut img = png::Image {
            width: left_width,
            height: left_height,
            pixels: png::PixelsByColorType::RGBA8(pixels),
        };
        let res = png::store_png(&mut img, &output);
        assert!(res.is_ok());

        match (reftest.kind, reftest.is_flaky) {
            (ReftestKind::Same, true) => println!("flaky test - rendering difference: {}", output),
            (ReftestKind::Same, false) => panic!("rendering difference: {}", output),
            (ReftestKind::Different, _) => {}   // Result was different and that's what was expected
        }
    } else {
        assert!(reftest.is_flaky || reftest.kind == ReftestKind::Same);
    }
}
<commit_msg>Record reference test stdout and stderr<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

#![feature(fs_walk)]
#![feature(path_ext)]
#![feature(slice_patterns)]
#![feature(test)]

#[macro_use] extern crate bitflags;
extern crate png;
extern crate test;
extern crate url;
extern crate util;

use std::env;
use std::ffi::OsStr;
use std::fs::{PathExt, File, walk_dir};
use std::io::{self, Read, Result, Write};
use std::path::{Path, PathBuf};
use std::process;
use std::process::{Command};
use std::thread::sleep_ms;
use test::run_tests_console;
use test::{AutoColor, DynTestName, DynTestFn, TestDesc, TestOpts, TestDescAndFn, ShouldPanic};
use url::Url;

bitflags!(
    flags RenderMode: u32 {
        const CPU_RENDERING  = 0x00000001,
        const GPU_RENDERING  = 0x00000010,
        const LINUX_TARGET   = 0x00000100,
        const MACOS_TARGET   = 0x00001000,
        const ANDROID_TARGET = 0x00010000
    }
);

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut parts = args[1..].split(|e| &**e == "--");

    let harness_args = parts.next().unwrap();  // .split() is never empty
    let servo_args = parts.next().unwrap_or(&[]);

    let (render_mode_string, base_path, testnames) = match harness_args {
        [ref render_mode_string, ref base_path, testnames..] =>
            (render_mode_string, base_path, testnames),
        _ => panic!("USAGE: cpu|gpu base_path [testname ...]"),
    };

    let mut render_mode = match &**render_mode_string {
        "cpu" => CPU_RENDERING,
        "gpu" => GPU_RENDERING,
        _ => panic!("First argument must specify cpu or gpu as rendering mode")
    };
    if cfg!(target_os = "linux") {
        render_mode.insert(LINUX_TARGET);
    }
    if cfg!(target_os = "macos") {
        render_mode.insert(MACOS_TARGET);
    }
    if cfg!(target_os = "android") {
        render_mode.insert(ANDROID_TARGET);
    }

    let mut all_tests = vec!();
    println!("Scanning {} for manifests\n", base_path);

    for file in walk_dir(base_path).unwrap() {
        let file = file.unwrap().path();
        let maybe_extension = file.extension();
        match maybe_extension {
            Some(extension) => {
                if extension == OsStr::new("list") && file.is_file() {
                    let len = all_tests.len();
                    let mut tests = parse_lists(&file, testnames, servo_args, render_mode, len);
                    println!("\t{} [{} tests]", file.display(), tests.len());
                    all_tests.append(&mut tests);
                }
            }
            _ => {}
        }
    }

    let test_opts = TestOpts {
        filter: None,
        run_ignored: false,
        logfile: None,
        run_tests: true,
        bench_benchmarks: false,
        nocapture: false,
        color: AutoColor,
    };

    match run(test_opts,
              all_tests,
              servo_args.iter().map(|x| x.clone()).collect()) {
        Ok(false) => process::exit(1), // tests failed
        Err(_) => process::exit(2),    // I/O-related failure
        _ => (),
    }
}

fn run(test_opts: TestOpts, all_tests: Vec<TestDescAndFn>,
       servo_args: Vec<String>) -> io::Result<bool> {
    // Verify that we're passing in valid servo arguments. Otherwise, servo
    // will exit before we've run any tests, and it will appear to us as if
    // all the tests are failing.
    let mut command = Command::new(&servo_path());
    command
        .args(&servo_args)
        .arg("-z")
        .arg("about:blank");

    let mut child = match command.spawn() {
        Ok(p) => p,
        Err(e) => panic!("failed to execute process: {}", e),
    };

    // Wait for the shell to launch or to fail
    sleep_ms(1000);
    child.kill().unwrap();
    let output = try!(child.wait_with_output());

    let stderr = String::from_utf8(output.stderr).unwrap();

    if stderr.contains("Unrecognized") {
        println!("Servo: {}", stderr);
        return Ok(false);
    }

    run_tests_console(&test_opts, all_tests)
}

#[derive(PartialEq)]
enum ReftestKind {
    Same,
    Different,
}

struct Reftest {
    name: String,
    kind: ReftestKind,
    files: [PathBuf; 2],
    id: usize,
    servo_args: Vec<String>,
    render_mode: RenderMode,
    is_flaky: bool,
    prefs: Vec<String>,
    fragment_identifier: Option<String>,
    resolution: Option<String>,
    pixel_ratio: Option<f32>,
}

struct TestLine<'a> {
    conditions: &'a str,
    kind: &'a str,
    file_left: &'a str,
    file_right: &'a str,
}

fn parse_lists(file: &Path,
               filters: &[String],
               servo_args: &[String],
               render_mode: RenderMode,
               id_offset: usize)
               -> Vec<TestDescAndFn> {
    let mut tests = Vec::new();
    let contents = {
        let mut f = File::open(file).unwrap();
        let mut contents = String::new();
        f.read_to_string(&mut contents).unwrap();
        contents
    };

    for line in contents.lines() {
        // ignore comments or empty lines
        if line.starts_with("#") || line.is_empty() {
            continue;
        }

        let parts: Vec<&str> = line.split(' ').filter(|p| !p.is_empty()).collect();

        let test_line = match parts.len() {
            3 => TestLine {
                conditions: "",
                kind: parts[0],
                file_left: parts[1],
                file_right: parts[2],
            },
            4 => TestLine {
                conditions: parts[0],
                kind: parts[1],
                file_left: parts[2],
                file_right: parts[3],
            },
            _ => panic!("reftest line: '{}' doesn't match '[CONDITIONS] KIND LEFT RIGHT'", line),
        };

        let kind = match test_line.kind {
            "==" => ReftestKind::Same,
            "!=" => ReftestKind::Different,
            part => panic!("reftest line: '{}' has invalid kind '{}'", line, part)
        };

        let base = env::current_dir().unwrap().join(file.parent().unwrap());

        let file_left =  base.join(test_line.file_left);
        let file_right = base.join(test_line.file_right);

        let conditions_list = test_line.conditions.split(',');
        let mut flakiness = RenderMode::empty();
        let mut prefs = vec![];
        let mut fragment_identifier = None;
        let mut resolution = None;
        let mut pixel_ratio = None;
        for condition in conditions_list {
            match condition {
                "flaky_cpu" => flakiness.insert(CPU_RENDERING),
                "flaky_gpu" => flakiness.insert(GPU_RENDERING),
                "flaky_linux" => flakiness.insert(LINUX_TARGET),
                "flaky_macos" => flakiness.insert(MACOS_TARGET),
                _ => ()
            }
            if condition.starts_with("prefs:\"") {
                if let Some(joined) = condition.split("\"").nth(1) {
                    prefs.extend(joined.split(",").map(str::to_owned));
                }
            }
            if condition.starts_with("fragment=") {
                fragment_identifier = Some(condition["fragment=".len()..].to_string());
            }
            if condition.starts_with("resolution=") {
                resolution = Some(condition["resolution=".len() ..].to_string());
            }
            if condition.starts_with("device-pixel-ratio=") {
                pixel_ratio = Some(condition["device-pixel-ratio=".len() ..].to_string()
                                   .parse().expect("Invalid device-pixel-ratio"));
            }
        }

        let reftest = Reftest {
            name: format!("{} {} {}", test_line.file_left, test_line.kind, test_line.file_right),
            kind: kind,
            files: [file_left, file_right],
            id: id_offset + tests.len(),
            render_mode: render_mode,
            servo_args: servo_args.to_vec(),
            is_flaky: render_mode.intersects(flakiness),
            prefs: prefs,
            fragment_identifier: fragment_identifier,
            resolution: resolution,
            pixel_ratio: pixel_ratio,
        };

        if filters.is_empty() || filters.iter().any(|pattern| reftest.name.contains(pattern)) {
            tests.push(make_test(reftest));
        }
    }
    tests
}

fn make_test(reftest: Reftest) -> TestDescAndFn {
    let name = reftest.name.clone();
    TestDescAndFn {
        desc: TestDesc {
            name: DynTestName(name),
            ignore: false,
            should_panic: ShouldPanic::No,
        },
        testfn: DynTestFn(Box::new(move || {
            check_reftest(reftest);
        })),
    }
}

fn capture(reftest: &Reftest, side: usize) -> (u32, u32, Vec<u8>) {
    let png_filename = format!("/tmp/servo-reftest-{:06}-{}.png", reftest.id, side);
    let mut command = Command::new(&servo_path());
    command
        .args(&reftest.servo_args[..])
        .arg("--user-stylesheet").arg(util::resource_files::resources_dir_path().join("ahem.css"))
        // Allows pixel perfect rendering of Ahem font and the HTML canvas for reftests.
        .arg("-Z")
        .arg("disable-text-aa,disable-canvas-aa")
        .args(&["-f", "-o"])
        .arg(&png_filename)
        .arg(&{
            let mut url = Url::from_file_path(&*reftest.files[side]).unwrap();
            url.fragment = reftest.fragment_identifier.clone();
            url.to_string()
        });
    // CPU rendering is the default
    if reftest.render_mode.contains(CPU_RENDERING) {
        command.arg("-c");
    }
    if reftest.render_mode.contains(GPU_RENDERING) {
        command.arg("-g");
    }
    for pref in &reftest.prefs {
        command.arg("--pref");
        command.arg(pref);
    }
    if let Some(ref resolution) = reftest.resolution {
        command.arg("--resolution");
        command.arg(resolution);
    }
    if let Some(pixel_ratio) = reftest.pixel_ratio {
        command.arg("--device-pixel-ratio");
        command.arg(pixel_ratio.to_string());
    }
    let (exit_status, stderr, stdout) = match command.output() {
        Ok(output) => (output.status, output.stderr, output.stdout),
        Err(e) => panic!("failed to execute process: {}", e),
    };

    if !stdout.is_empty() {
        let stdout_filename = format!("/tmp/servo-reftest-{:06}-{}-stdout.txt", reftest.id, side);
        let mut stdout_file = File::create(stdout_filename).unwrap();
        stdout_file.write_all(&stdout[..]).unwrap();
    }

    if !stderr.is_empty() {
        let stderr_filename = format!("/tmp/servo-reftest-{:06}-{}-stderr.txt", reftest.id, side);
        let mut stderr_file = File::create(stderr_filename).unwrap();
        stderr_file.write_all(&stderr[..]).unwrap();
    }

    assert!(exit_status.success());

    let image = png::load_png(&png_filename).unwrap();
    let rgba8_bytes = match image.pixels {
        png::PixelsByColorType::RGBA8(pixels) => pixels,
        _ => panic!(),
    };
    (image.width, image.height, rgba8_bytes)
}

fn servo_path() -> PathBuf {
    let current_exe = env::current_exe().ok().expect("Could not locate current executable");
    current_exe.parent().unwrap().join("servo")
}

fn check_reftest(reftest: Reftest) {
    let (left_width, left_height, left_bytes) = capture(&reftest, 0);
    let (right_width, right_height, right_bytes) = capture(&reftest, 1);

    assert_eq!(left_width, right_width);
    assert_eq!(left_height, right_height);

    let left_all_white = left_bytes.iter().all(|&p| p == 255);
    let right_all_white = right_bytes.iter().all(|&p| p == 255);

    if left_all_white && right_all_white {
        panic!("Both renderings are empty")
    }

    let pixels = left_bytes.iter().zip(right_bytes.iter()).map(|(&a, &b)| {
        if a == b {
            // White for correct
            0xFF
        } else {
            // "1100" in the RGBA channel with an error for an incorrect value
            // This results in some number of C0 and FFs, which is much more
            // readable (and distinguishable) than the previous difference-wise
            // scaling but does not require reconstructing the actual RGBA pixel.
            0xC0
        }
    }).collect::<Vec<u8>>();

    if pixels.iter().any(|&a| a < 255) {
        let output = format!("/tmp/servo-reftest-{:06}-diff.png", reftest.id);

        let mut img = png::Image {
            width: left_width,
            height: left_height,
            pixels: png::PixelsByColorType::RGBA8(pixels),
        };
        let res = png::store_png(&mut img, &output);
        assert!(res.is_ok());

        match (reftest.kind, reftest.is_flaky) {
            (ReftestKind::Same, true) => println!("flaky test - rendering difference: {}", output),
            (ReftestKind::Same, false) => panic!("rendering difference: {}", output),
            (ReftestKind::Different, _) => {}   // Result was different and that's what was expected
        }
    } else {
        assert!(reftest.is_flaky || reftest.kind == ReftestKind::Same);
    }
}
<|endoftext|>


<commit_before>use cairo;
use libc;
use librsvg::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use librsvg::{CairoRenderer, RenderingError};

use crate::reference_utils::{Compare, Evaluate, Reference};
use crate::utils::load_svg;

#[test]
fn has_element_with_id_works() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
  <rect id="foo" x="10" y="10" width="30" height="30"/>
</svg>
"#,
    )
    .unwrap();

    assert!(svg.has_element_with_id("#foo").unwrap());
    assert!(!svg.has_element_with_id("#bar").unwrap());

    assert!(matches!(
        svg.has_element_with_id(""),
        Err(RenderingError::InvalidId(_))
    ));

    assert!(matches!(
        svg.has_element_with_id("not a fragment"),
        Err(RenderingError::InvalidId(_))
    ));

    assert!(matches!(
        svg.has_element_with_id("notfragment#fragment"),
        Err(RenderingError::InvalidId(_))
    ));
}

#[test]
fn render_layer() {
    let svg = load_svg(
        br##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <rect id="foo" x="10" y="10" width="30" height="30" fill="#00ff00"/>
  <rect id="bar" x="20" y="20" width="30" height="30" fill="#0000ff"/>
</svg>
"##,
    )
    .unwrap();

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 300, 300).unwrap();

    let res = {
        let cr = cairo::Context::new(&output).expect("Failed to create cairo context");
        let viewport = cairo::Rectangle {
            x: 100.0,
            y: 100.0,
            width: 100.0,
            height: 100.0,
        };

        renderer.render_layer(&cr, Some("#bar"), &viewport)
    };

    let output_surf = res
        .and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb).unwrap()))
        .unwrap();

    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 300, 300).unwrap();

    {
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");

        cr.translate(100.0, 100.0);

        cr.rectangle(20.0, 20.0, 30.0, 30.0);
        cr.set_source_rgba(0.0, 0.0, 1.0, 1.0);
        cr.fill().unwrap();
    }

    Reference::from_surface(reference_surf)
        .compare(&output_surf)
        .evaluate(&output_surf, "render_layer");
}

#[test]
fn untransformed_element() {
    // This has a rectangle inside a transformed group.  The rectangle
    // inherits its stroke-width from the group.
    //
    // The idea is that we'll be able to extract the geometry of the rectangle
    // as if it were not transformed by its ancestors, but still retain the
    // cascade from the ancestors.
    let svg = load_svg(
        br##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <g transform="rotate(45)" stroke-width="10" stroke="#000000">
    <rect id="foo" x="10" y="20" width="30" height="40" fill="#0000ff"/>
  </g>
</svg>
"##,
    )
    .unwrap();

    let renderer = CairoRenderer::new(&svg);

    /* Measuring */

    let (ink_r, logical_r) = renderer.geometry_for_element(Some("#foo")).unwrap();

    assert_eq!(
        ink_r,
        cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 40.0,
            height: 50.0,
        }
    );

    assert_eq!(
        logical_r,
        cairo::Rectangle {
            x: 5.0,
            y: 5.0,
            width: 30.0,
            height: 40.0,
        }
    );

    /* Rendering */

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 300, 300).unwrap();

    let res = {
        let cr = cairo::Context::new(&output).expect("Failed to create cairo context");
        let viewport = cairo::Rectangle {
            x: 100.0,
            y: 100.0,
            width: 100.0,
            height: 100.0,
        };

        renderer.render_element(&cr, Some("#foo"), &viewport)
    };

    let output_surf = res
        .and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb).unwrap()))
        .unwrap();

    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 300, 300).unwrap();

    {
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");

        cr.translate(100.0, 100.0);

        cr.rectangle(10.0, 10.0, 60.0, 80.0);
        cr.set_source_rgba(0.0, 0.0, 1.0, 1.0);
        cr.fill_preserve().unwrap();

        cr.set_line_width(20.0);
        cr.set_source_rgba(0.0, 0.0, 0.0, 1.0);
        cr.stroke().unwrap();
    }

    Reference::from_surface(reference_surf)
        .compare(&output_surf)
        .evaluate(&output_surf, "untransformed_element");
}

#[test]
fn set_stylesheet() {
    // This has a rectangle which we style from a user-supplied stylesheet.
    let mut svg = load_svg(
        br##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <rect id="foo" x="10" y="20" width="30" height="40" fill="black"/>
</svg>
"##,
    )
    .unwrap();

    svg.set_stylesheet("rect { fill: #00ff00; }")
        .expect("should be a valid stylesheet");

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();

    let res = {
        let cr = cairo::Context::new(&output).expect("Failed to create cairo context");
        let viewport = cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 100.0,
            height: 100.0,
        };

        renderer.render_document(&cr, &viewport)
    };

    let output_surf = res
        .and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb).unwrap()))
        .unwrap();

    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();

    {
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");

        cr.rectangle(10.0, 20.0, 30.0, 40.0);
        cr.set_source_rgba(0.0, 1.0, 0.0, 1.0);
        cr.fill().unwrap();
    }

    Reference::from_surface(reference_surf)
        .compare(&output_surf)
        .evaluate(&output_surf, "set_stylesheet");
}

fn has_current_point(cr: &cairo::Context) -> bool {
    // https://github.com/gtk-rs/gtk-rs-core/issues/335
    //
    // cairo-rs-sys incorrectly declares cairo_bool_t as a repr(C)
    // struct; it needs to be repr(transparent).  So, we'll call
    // has_current_point by hand.

    extern "C" {
        fn cairo_has_current_point(cr: *mut cairo::ffi::cairo_t) -> libc::c_int;
    }

    unsafe { cairo_has_current_point(cr.to_raw_none()) != 0 }
}

// https://gitlab.gnome.org/GNOME/librsvg/-/issues/799
#[test]
fn text_doesnt_leave_points_in_current_path() {
    let svg = load_svg(
        br##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <text>Hello world!</text>
</svg>
"##,
    )
    .unwrap();

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();
    let cr = cairo::Context::new(&output).unwrap();

    assert!(!has_current_point(&cr));

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    renderer.render_document(&cr, &viewport).unwrap();

    assert!(!has_current_point(&cr));
}
<commit_msg>tests: revert the cairo workaround in !627<commit_after>use cairo;
use librsvg::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use librsvg::{CairoRenderer, RenderingError};

use crate::reference_utils::{Compare, Evaluate, Reference};
use crate::utils::load_svg;

#[test]
fn has_element_with_id_works() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">
  <rect id="foo" x="10" y="10" width="30" height="30"/>
</svg>
"#,
    )
    .unwrap();

    assert!(svg.has_element_with_id("#foo").unwrap());
    assert!(!svg.has_element_with_id("#bar").unwrap());

    assert!(matches!(
        svg.has_element_with_id(""),
        Err(RenderingError::InvalidId(_))
    ));

    assert!(matches!(
        svg.has_element_with_id("not a fragment"),
        Err(RenderingError::InvalidId(_))
    ));

    assert!(matches!(
        svg.has_element_with_id("notfragment#fragment"),
        Err(RenderingError::InvalidId(_))
    ));
}

#[test]
fn render_layer() {
    let svg = load_svg(
        br##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <rect id="foo" x="10" y="10" width="30" height="30" fill="#00ff00"/>
  <rect id="bar" x="20" y="20" width="30" height="30" fill="#0000ff"/>
</svg>
"##,
    )
    .unwrap();

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 300, 300).unwrap();

    let res = {
        let cr = cairo::Context::new(&output).expect("Failed to create cairo context");
        let viewport = cairo::Rectangle {
            x: 100.0,
            y: 100.0,
            width: 100.0,
            height: 100.0,
        };

        renderer.render_layer(&cr, Some("#bar"), &viewport)
    };

    let output_surf = res
        .and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb).unwrap()))
        .unwrap();

    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 300, 300).unwrap();

    {
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");

        cr.translate(100.0, 100.0);

        cr.rectangle(20.0, 20.0, 30.0, 30.0);
        cr.set_source_rgba(0.0, 0.0, 1.0, 1.0);
        cr.fill().unwrap();
    }

    Reference::from_surface(reference_surf)
        .compare(&output_surf)
        .evaluate(&output_surf, "render_layer");
}

#[test]
fn untransformed_element() {
    // This has a rectangle inside a transformed group.  The rectangle
    // inherits its stroke-width from the group.
    //
    // The idea is that we'll be able to extract the geometry of the rectangle
    // as if it were not transformed by its ancestors, but still retain the
    // cascade from the ancestors.
    let svg = load_svg(
        br##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <g transform="rotate(45)" stroke-width="10" stroke="#000000">
    <rect id="foo" x="10" y="20" width="30" height="40" fill="#0000ff"/>
  </g>
</svg>
"##,
    )
    .unwrap();

    let renderer = CairoRenderer::new(&svg);

    /* Measuring */

    let (ink_r, logical_r) = renderer.geometry_for_element(Some("#foo")).unwrap();

    assert_eq!(
        ink_r,
        cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 40.0,
            height: 50.0,
        }
    );

    assert_eq!(
        logical_r,
        cairo::Rectangle {
            x: 5.0,
            y: 5.0,
            width: 30.0,
            height: 40.0,
        }
    );

    /* Rendering */

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 300, 300).unwrap();

    let res = {
        let cr = cairo::Context::new(&output).expect("Failed to create cairo context");
        let viewport = cairo::Rectangle {
            x: 100.0,
            y: 100.0,
            width: 100.0,
            height: 100.0,
        };

        renderer.render_element(&cr, Some("#foo"), &viewport)
    };

    let output_surf = res
        .and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb).unwrap()))
        .unwrap();

    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 300, 300).unwrap();

    {
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");

        cr.translate(100.0, 100.0);

        cr.rectangle(10.0, 10.0, 60.0, 80.0);
        cr.set_source_rgba(0.0, 0.0, 1.0, 1.0);
        cr.fill_preserve().unwrap();

        cr.set_line_width(20.0);
        cr.set_source_rgba(0.0, 0.0, 0.0, 1.0);
        cr.stroke().unwrap();
    }

    Reference::from_surface(reference_surf)
        .compare(&output_surf)
        .evaluate(&output_surf, "untransformed_element");
}

#[test]
fn set_stylesheet() {
    // This has a rectangle which we style from a user-supplied stylesheet.
    let mut svg = load_svg(
        br##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <rect id="foo" x="10" y="20" width="30" height="40" fill="black"/>
</svg>
"##,
    )
    .unwrap();

    svg.set_stylesheet("rect { fill: #00ff00; }")
        .expect("should be a valid stylesheet");

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();

    let res = {
        let cr = cairo::Context::new(&output).expect("Failed to create cairo context");
        let viewport = cairo::Rectangle {
            x: 0.0,
            y: 0.0,
            width: 100.0,
            height: 100.0,
        };

        renderer.render_document(&cr, &viewport)
    };

    let output_surf = res
        .and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb).unwrap()))
        .unwrap();

    let reference_surf = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();

    {
        let cr = cairo::Context::new(&reference_surf).expect("Failed to create a cairo context");

        cr.rectangle(10.0, 20.0, 30.0, 40.0);
        cr.set_source_rgba(0.0, 1.0, 0.0, 1.0);
        cr.fill().unwrap();
    }

    Reference::from_surface(reference_surf)
        .compare(&output_surf)
        .evaluate(&output_surf, "set_stylesheet");
}

// https://gitlab.gnome.org/GNOME/librsvg/-/issues/799
#[test]
fn text_doesnt_leave_points_in_current_path() {
    let svg = load_svg(
        br##"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <text>Hello world!</text>
</svg>
"##,
    )
    .unwrap();

    let renderer = CairoRenderer::new(&svg);

    let output = cairo::ImageSurface::create(cairo::Format::ARgb32, 100, 100).unwrap();
    let cr = cairo::Context::new(&output).unwrap();

    assert!(!cr.has_current_point().unwrap());

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    renderer.render_document(&cr, &viewport).unwrap();

    assert!(!cr.has_current_point().unwrap());
}
<|endoftext|>


<commit_before>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::{ast::NodeId, source_map::Span};
use crate::utils::{snippet_opt, span_lint_and_then};

/// **What it does:** Checks for missing return statements at the end of a block.
///
/// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers
/// coming from other languages might prefer the expressiveness of `return`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(x: usize) {
///     x
/// }
/// ```
/// add return
/// ```rust
/// fn foo(x: usize) {
///     return x;
/// }
/// ```
declare_clippy_lint! {
    pub IMPLICIT_RETURN,
    restriction,
    "use a return statement like `return expr` instead of an expression"
}

pub struct Pass;

impl Pass {
    fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) {
        match &expr.node {
            ExprKind::Block(block, ..) => {
                if let Some(expr) = &block.expr {
                    Self::expr_match(cx, expr);
                }
                // only needed in the case of `break` with `;` at the end
                else if let Some(stmt) = block.stmts.last() {
                    if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node {
                        Self::expr_match(cx, expr);
                    }
                }
            },
            // use `return` instead of `break`
            ExprKind::Break(.., break_expr) => {
                if let Some(break_expr) = break_expr {
                    span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| {
                        if let Some(snippet) = snippet_opt(cx, break_expr.span) {
                            db.span_suggestion_with_applicability(
                                expr.span,
                                "change `break` to `return` as shown",
                                format!("return {}", snippet),
                                Applicability::MachineApplicable,
                            );
                        }
                    });
                }
            },
            ExprKind::If(.., if_expr, else_expr) => {
                Self::expr_match(cx, if_expr);

                if let Some(else_expr) = else_expr {
                    Self::expr_match(cx, else_expr);
                }
            },
            ExprKind::Match(_, arms, ..) => {
                for arm in arms {
                    Self::expr_match(cx, &arm.body);
                }
            },
            // loops could be using `break` instead of `return`
            ExprKind::Loop(block, ..) => {
                if let Some(expr) = &block.expr {
                    Self::expr_match(cx, expr);
                }
            },
            // skip if it already has a return statement
            ExprKind::Ret(..) => (),
            // everything else is missing `return`
            _ => span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| {
                if let Some(snippet) = snippet_opt(cx, expr.span) {
                    db.span_suggestion_with_applicability(
                        expr.span,
                        "add `return` as shown",
                        format!("return {}", snippet),
                        Applicability::MachineApplicable,
                    );
                }
            }),
        }
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(IMPLICIT_RETURN)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx FnDecl,
        body: &'tcx Body,
        _: Span,
        _: NodeId,
    ) {
        let def_id = cx.tcx.hir.body_owner_def_id(body.id());
        let mir = cx.tcx.optimized_mir(def_id);

        if !mir.return_ty().is_unit() {
            Self::expr_match(cx, &body.value);
        }
    }
}
<commit_msg>Added additional reasoning to `Why is this bad?`. Added comment to explain usage of MIR.<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::{ast::NodeId, source_map::Span};
use crate::utils::{snippet_opt, span_lint_and_then};

/// **What it does:** Checks for missing return statements at the end of a block.
///
/// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers
/// coming from other languages might prefer the expressiveness of `return`. It's possible to miss
/// the last returning statement because the only difference is a missing `;`. Especially in bigger
/// code with multiple return paths having a `return` keyword makes it easier to find the
/// corresponding statements.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(x: usize) {
///     x
/// }
/// ```
/// add return
/// ```rust
/// fn foo(x: usize) {
///     return x;
/// }
/// ```
declare_clippy_lint! {
    pub IMPLICIT_RETURN,
    restriction,
    "use a return statement like `return expr` instead of an expression"
}

pub struct Pass;

impl Pass {
    fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) {
        match &expr.node {
            ExprKind::Block(block, ..) => {
                if let Some(expr) = &block.expr {
                    Self::expr_match(cx, expr);
                }
                // only needed in the case of `break` with `;` at the end
                else if let Some(stmt) = block.stmts.last() {
                    if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node {
                        Self::expr_match(cx, expr);
                    }
                }
            },
            // use `return` instead of `break`
            ExprKind::Break(.., break_expr) => {
                if let Some(break_expr) = break_expr {
                    span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| {
                        if let Some(snippet) = snippet_opt(cx, break_expr.span) {
                            db.span_suggestion_with_applicability(
                                expr.span,
                                "change `break` to `return` as shown",
                                format!("return {}", snippet),
                                Applicability::MachineApplicable,
                            );
                        }
                    });
                }
            },
            ExprKind::If(.., if_expr, else_expr) => {
                Self::expr_match(cx, if_expr);

                if let Some(else_expr) = else_expr {
                    Self::expr_match(cx, else_expr);
                }
            },
            ExprKind::Match(_, arms, ..) => {
                for arm in arms {
                    Self::expr_match(cx, &arm.body);
                }
            },
            // loops could be using `break` instead of `return`
            ExprKind::Loop(block, ..) => {
                if let Some(expr) = &block.expr {
                    Self::expr_match(cx, expr);
                }
            },
            // skip if it already has a return statement
            ExprKind::Ret(..) => (),
            // everything else is missing `return`
            _ => span_lint_and_then(cx, IMPLICIT_RETURN, expr.span, "missing return statement", |db| {
                if let Some(snippet) = snippet_opt(cx, expr.span) {
                    db.span_suggestion_with_applicability(
                        expr.span,
                        "add `return` as shown",
                        format!("return {}", snippet),
                        Applicability::MachineApplicable,
                    );
                }
            }),
        }
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(IMPLICIT_RETURN)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx FnDecl,
        body: &'tcx Body,
        _: Span,
        _: NodeId,
    ) {
        let def_id = cx.tcx.hir.body_owner_def_id(body.id());
        let mir = cx.tcx.optimized_mir(def_id);

        // checking return type through MIR, HIR is not able to determine inferred closure return types
        if !mir.return_ty().is_unit() {
            Self::expr_match(cx, &body.value);
        }
    }
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;

pub mod prelude;

use std::marker::PhantomData;

use num::Float;
use rand::distributions::IndependentSample;
use rand::distributions::range::Range;
use prelude::*;

const DIM_IN: usize = 2;
const DIM_HI: usize = 3;
const DIM_OU: usize = 1;

pub struct ConstantLearningRate;

impl<T> LearningRate<T> for ConstantLearningRate {
  #[inline(always)] fn lrate(_: &T) -> f64 { 0.1f64 }
}

pub struct DefaultMomentumConstant;

impl MomentumConstant for DefaultMomentumConstant {
  #[inline(always)] fn momentum() -> f64 { 0.3f64 }
}

pub struct DefaultErrorGradient;

impl ErrorGradient for DefaultErrorGradient {
  fn errhidden(act: f64, sum: f64) -> f64 { act * (1f64 - act) * sum }
  fn erroutput(exp: f64, act: f64) -> f64 { act * (1f64 - act) * (act - exp) }
}

pub struct TanhNeuralNet;

impl ActivationFunction for TanhNeuralNet {
  #[inline(always)] fn activation(x: f64) -> f64 { x.tanh() }
}

impl WeightFunction for TanhNeuralNet {
  #[inline] fn initw(ins: usize, outs: usize) -> f64 {
    let lb = -(6f64 / (ins as f64 + outs as f64)).sqrt();
    let ub =  (6f64 / (ins as f64 + outs as f64)).sqrt();
    let range = Range::new(lb, ub);
    let mut rng = rand::thread_rng();

    range.ind_sample(&mut rng)
  }
}

impl<T> Parameters<T> for TanhNeuralNet where T : MLNeuralNet {
  type LearningRate       = ConstantLearningRate;
  type ErrorGradient      = DefaultErrorGradient;
  type MomentumConstant   = DefaultMomentumConstant;
  type ActivationFunction = TanhNeuralNet;
  type WeightFunction     = TanhNeuralNet;
}

pub struct SigmoidNeuralNet;

impl ActivationFunction for SigmoidNeuralNet {
  #[inline(always)] fn activation(x: f64) -> f64 { 1f64 / (1f64 + -x.exp()) }
}

impl WeightFunction for SigmoidNeuralNet {
  #[inline] fn initw(ins: usize, outs: usize) -> f64 {
    let lb = -4f64 * (6f64 / (ins as f64 + outs as f64)).sqrt();
    let ub =  4f64 * (6f64 / (ins as f64 + outs as f64)).sqrt();
    let range = Range::new(lb, ub);
    let mut rng = rand::thread_rng();

    range.ind_sample(&mut rng)
  }
}

impl<T> Parameters<T> for SigmoidNeuralNet where T : MLNeuralNet
{
  type LearningRate       = ConstantLearningRate;
  type ErrorGradient      = DefaultErrorGradient;
  type MomentumConstant   = DefaultMomentumConstant;
  type ActivationFunction = SigmoidNeuralNet;
  type WeightFunction     = SigmoidNeuralNet;
}

pub struct XORNeuralNet

{
  input   : [f64; DIM_IN + 1],
  hidden  : [f64; DIM_HI + 1],
  output  : [f64; DIM_OU],
  winput  : [[f64; DIM_HI]; DIM_IN + 1],
  woutput : [[f64; DIM_OU]; DIM_HI + 1],
  dinput  : [[f64; DIM_HI]; DIM_IN + 1],
  doutput : [[f64; DIM_OU]; DIM_HI + 1],
  ehidden : [f64; DIM_HI + 1],
  eoutput : [f64; DIM_OU + 1],
  ptype   : PhantomData

}

impl
 MLNeuralNet for XORNeuralNet
 where P : Parameters<XORNeuralNet
>
{
  #[inline(always)] fn diminput() -> usize { DIM_IN }
  #[inline(always)] fn dimhidden() -> usize { DIM_HI }
  #[inline(always)] fn dimoutput() -> usize { DIM_OU }

  fn feedforward(&mut self, ins: &[f64]) {
    assert!(ins.len() == Self::diminput());

    self.input[0] = ins[0];
    self.input[1] = ins[1];

    self.hidden[0] = 0f64;
    self.hidden[1] = 0f64;
    self.hidden[2] = 0f64;

    self.hidden[0] += self.input[0] * self.winput[0][0];
    self.hidden[0] += self.input[1] * self.winput[1][0];
    self.hidden[0] += self.input[2] * self.winput[2][0];

    self.hidden[0] = P::ActivationFunction::activation(self.hidden[0]);

    self.hidden[1] += self.input[0] * self.winput[0][1];
    self.hidden[1] += self.input[1] * self.winput[1][1];
    self.hidden[1] += self.input[2] * self.winput[2][1];

    self.hidden[1] = P::ActivationFunction::activation(self.hidden[1]);

    self.hidden[2] += self.input[0] * self.winput[0][2];
    self.hidden[2] += self.input[1] * self.winput[1][2];
    self.hidden[2] += self.input[2] * self.winput[2][2];

    self.hidden[2] = P::ActivationFunction::activation(self.hidden[2]);

    self.output[0] = 0f64;

    self.output[0] += self.hidden[0] * self.woutput[0][0];
    self.output[0] += self.hidden[1] * self.woutput[1][0];
    self.output[0] += self.hidden[2] * self.woutput[2][0];
    self.output[0] += self.hidden[3] * self.woutput[3][0];

    self.output[0] = P::ActivationFunction::activation(self.output[0]);
  }

  fn backpropagate(&mut self, exp: &[f64]) {
    assert!(exp.len() == Self::dimoutput());

    self.eoutput[0] = P::ErrorGradient::erroutput(exp[0], self.output[0]);

    self.doutput[0][0] = P::LearningRate::lrate(&self as &XORNeuralNet
) *
      self.hidden[0] * self.eoutput[0] +
      P::MomentumConstant::momentum() * self.doutput[0][0];
    self.doutput[1][0] = P::LearningRate::lrate(&self as &XORNeuralNet
) *
      self.hidden[1] * self.eoutput[0] +
      P::MomentumConstant::momentum() * self.doutput[1][0];
    self.doutput[2][0] = P::LearningRate::lrate(&self as &XORNeuralNet
) *
      self.hidden[2] * self.eoutput[0] +
      P::MomentumConstant::momentum() * self.doutput[2][0];
    self.doutput[3][0] = P::LearningRate::lrate(&self as &XORNeuralNet
) *
      self.hidden[3] * self.eoutput[0] +
      P::MomentumConstant::momentum() * self.doutput[3][0];
  }
}

impl
 XORNeuralNet
 where P : Parameters<XORNeuralNet
>
{
  pub fn new() -> XORNeuralNet
 where P : Parameters<XORNeuralNet
>
  {
    macro_rules! initw (
      () => {
        P::WeightFunction::initw(Self::diminput(), Self::dimoutput())
      }
    );

    XORNeuralNet {
      input   : [0f64, 0f64, -1f64],
      hidden  : [0f64, 0f64, 0f64, -1f64],
      output  : [0f64],
      winput  : [
        [initw!(), initw!(), initw!()],
        [initw!(), initw!(), initw!()],
        [initw!(), initw!(), initw!()]
      ],
      woutput : [[initw!()], [initw!()], [initw!()], [initw!()]],
      dinput  : [[0f64, 0f64, 0f64], [0f64, 0f64, 0f64], [0f64, 0f64, 0f64]],
      doutput : [[0f64], [0f64], [0f64], [0f64]],
      ehidden : [0f64, 0f64, 0f64, 0f64],
      eoutput : [0f64, 0f64],
      ptype   : PhantomData
    }
  }
}

#[test]
fn weights() {
  let xor = [
    (vec![0f64, 0f64], [0f64]),
    (vec![0f64, 1f64], [1f64]),
    (vec![1f64, 0f64], [1f64]),
    (vec![1f64, 1f64], [0f64])
  ];
  let mut nn: XORNeuralNet<SigmoidNeuralNet> = XORNeuralNet::new();

  println!("");

  for &(ref v, ref e) in xor.iter() {
    nn.feedforward(&v[..]);
    nn.backpropagate(&e[..]);

    println!("input   : {:?}", nn.input);
    println!("hidden  : {:?}", nn.hidden);
    println!("output  : {:?}", nn.output);
    println!("");
  }

  assert!(false);
}
<commit_msg>converted into loops<commit_after>extern crate num;
extern crate rand;

pub mod prelude;

use std::marker::PhantomData;

use num::Float;
use rand::distributions::IndependentSample;
use rand::distributions::range::Range;
use prelude::*;

const DIM_IN: usize = 2;
const DIM_HI: usize = 3;
const DIM_OU: usize = 1;

pub struct ConstantLearningRate;

impl<T> LearningRate<T> for ConstantLearningRate {
  #[inline(always)] fn lrate(_: &T) -> f64 { 0.1f64 }
}

pub struct DefaultMomentumConstant;

impl MomentumConstant for DefaultMomentumConstant {
  #[inline(always)] fn momentum() -> f64 { 0.3f64 }
}

pub struct DefaultErrorGradient;

impl ErrorGradient for DefaultErrorGradient {
  fn errhidden(act: f64, sum: f64) -> f64 { act * (1f64 - act) * sum }
  fn erroutput(exp: f64, act: f64) -> f64 { act * (1f64 - act) * (act - exp) }
}

pub struct TanhNeuralNet;

impl ActivationFunction for TanhNeuralNet {
  #[inline(always)] fn activation(x: f64) -> f64 { x.tanh() }
}

impl WeightFunction for TanhNeuralNet {
  #[inline] fn initw(ins: usize, outs: usize) -> f64 {
    let lb = -(6f64 / (ins as f64 + outs as f64)).sqrt();
    let ub =  (6f64 / (ins as f64 + outs as f64)).sqrt();
    let range = Range::new(lb, ub);
    let mut rng = rand::thread_rng();

    range.ind_sample(&mut rng)
  }
}

impl<T> Parameters<T> for TanhNeuralNet where T : MLNeuralNet {
  type LearningRate       = ConstantLearningRate;
  type ErrorGradient      = DefaultErrorGradient;
  type MomentumConstant   = DefaultMomentumConstant;
  type ActivationFunction = TanhNeuralNet;
  type WeightFunction     = TanhNeuralNet;
}

pub struct SigmoidNeuralNet;

impl ActivationFunction for SigmoidNeuralNet {
  #[inline(always)] fn activation(x: f64) -> f64 { 1f64 / (1f64 + -x.exp()) }
}

impl WeightFunction for SigmoidNeuralNet {
  #[inline] fn initw(ins: usize, outs: usize) -> f64 {
    let lb = -4f64 * (6f64 / (ins as f64 + outs as f64)).sqrt();
    let ub =  4f64 * (6f64 / (ins as f64 + outs as f64)).sqrt();
    let range = Range::new(lb, ub);
    let mut rng = rand::thread_rng();

    range.ind_sample(&mut rng)
  }
}

impl<T> Parameters<T> for SigmoidNeuralNet where T : MLNeuralNet
{
  type LearningRate       = ConstantLearningRate;
  type ErrorGradient      = DefaultErrorGradient;
  type MomentumConstant   = DefaultMomentumConstant;
  type ActivationFunction = SigmoidNeuralNet;
  type WeightFunction     = SigmoidNeuralNet;
}

pub struct XORNeuralNet

{
  input   : [f64; DIM_IN + 1],
  hidden  : [f64; DIM_HI + 1],
  output  : [f64; DIM_OU],
  winput  : [[f64; DIM_HI]; DIM_IN + 1],
  woutput : [[f64; DIM_OU]; DIM_HI + 1],
  dinput  : [[f64; DIM_HI]; DIM_IN + 1],
  doutput : [[f64; DIM_OU]; DIM_HI + 1],
  ehidden : [f64; DIM_HI + 1],
  eoutput : [f64; DIM_OU + 1],
  ptype   : PhantomData

}

impl
 MLNeuralNet for XORNeuralNet
 where P : Parameters<XORNeuralNet
>
{
  #[inline(always)] fn diminput() -> usize { DIM_IN }
  #[inline(always)] fn dimhidden() -> usize { DIM_HI }
  #[inline(always)] fn dimoutput() -> usize { DIM_OU }

  fn feedforward(&mut self, ins: &[f64]) {
    assert!(ins.len() == Self::diminput());

    for i in (0..Self::diminput()) {
      self.input[i] = ins[i];
    }

    for i in (0..Self::dimhidden()) {
      self.hidden[i] = 0f64;

      for j in (0..Self::diminput() + 1) {
        self.hidden[i] += self.input[j] * self.winput[j][i];
      }

      self.hidden[i] = P::ActivationFunction::activation(self.hidden[i]);
    }

    for i in (0..Self::dimoutput()) {
      self.output[i] = 0f64;

      for j in (0..Self::dimhidden() + 1) {
        self.output[i] += self.hidden[j] * self.woutput[j][i];
      }

      self.output[i] = P::ActivationFunction::activation(self.output[i]);
    }
  }

  fn backpropagate(&mut self, exp: &[f64]) {
    assert!(exp.len() == Self::dimoutput());

    for i in (0..Self::dimoutput()) {
      self.eoutput[i] = P::ErrorGradient::erroutput(exp[i], self.output[0]);

      for j in (0..Self::dimhidden() + 1) {
        self.doutput[j][i] = P::LearningRate::lrate(&self as &XORNeuralNet
) *
        self.hidden[j] * self.eoutput[i] +
        P::MomentumConstant::momentum() * self.doutput[j][i];
      }
    }

    for i in (0..Self::dimhidden()) {
      let wsum = (0..Self::dimoutput())
        .fold(0f64, |acc, j| acc + (self.woutput[i][j] * self.eoutput[j]));

      self.ehidden[i] = P::ErrorGradient::errhidden(self.hidden[i], wsum);

      for j in (0..Self::diminput() + 1) {
        self.dinput[j][i] = P::LearningRate::lrate(&self as &XORNeuralNet
) *
        self.input[j] * self.ehidden[i] +
        P::MomentumConstant::momentum() * self.dinput[j][i];
      }
    }

    for i in (0..Self::diminput() + 1) {
      for j in (0..Self::dimhidden()) {
        self.winput[i][j] += self.dinput[i][j];
      }
    }

    for i in (0..Self::dimhidden() + 1) {
      for j in (0..Self::dimoutput()) {
        self.woutput[i][j] += self.doutput[i][j];
      }
    }
  }
}

impl
 XORNeuralNet
 where P : Parameters<XORNeuralNet
>
{
  pub fn new() -> XORNeuralNet
 where P : Parameters<XORNeuralNet
>
  {
    macro_rules! initw (
      () => {
        P::WeightFunction::initw(Self::diminput(), Self::dimoutput())
      }
    );

    XORNeuralNet {
      input   : [0f64, 0f64, -1f64],
      hidden  : [0f64, 0f64, 0f64, -1f64],
      output  : [0f64],
      winput  : [
        [initw!(), initw!(), initw!()],
        [initw!(), initw!(), initw!()],
        [initw!(), initw!(), initw!()]
      ],
      woutput : [[initw!()], [initw!()], [initw!()], [initw!()]],
      dinput  : [[0f64, 0f64, 0f64], [0f64, 0f64, 0f64], [0f64, 0f64, 0f64]],
      doutput : [[0f64], [0f64], [0f64], [0f64]],
      ehidden : [0f64, 0f64, 0f64, 0f64],
      eoutput : [0f64, 0f64],
      ptype   : PhantomData
    }
  }
}

#[test]
fn weights() {
  let xor = [
    (vec![0f64, 0f64], [0f64]),
    (vec![0f64, 1f64], [1f64]),
    (vec![1f64, 0f64], [1f64]),
    (vec![1f64, 1f64], [0f64])
  ];
  let mut nn: XORNeuralNet<SigmoidNeuralNet> = XORNeuralNet::new();

  println!("");

  for &(ref v, ref e) in xor.iter() {
    nn.feedforward(&v[..]);
    nn.backpropagate(&e[..]);

    println!("input   : {:?}", nn.input);
    println!("hidden  : {:?}", nn.hidden);
    println!("output  : {:?}", nn.output);
    println!("");
  }

  assert!(false);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#[cfg(target_os = "android")]
use android_injected_glue;
#[cfg(not(target_os = "android"))]
use std::env;
#[cfg(target_os = "android")]
use std::ffi::CStr;
use std::fs::File;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};

lazy_static! {
    static ref CMD_RESOURCE_DIR: Arc<Mutex<Option<String>>> = {
        Arc::new(Mutex::new(None))
    };
}

pub fn set_resources_path(path: Option<String>) {
    let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
    *dir = path;
}

#[cfg(target_os = "android")]
#[allow(unsafe_code)]
pub fn resources_dir_path() -> io::Result<PathBuf> {
    let dir = unsafe {
        CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath)
    };
    Ok(PathBuf::from(dir.to_str().unwrap()))
}

#[cfg(not(target_os = "android"))]
pub fn resources_dir_path() -> io::Result<PathBuf> {
    let mut dir = CMD_RESOURCE_DIR.lock().unwrap();

    if let Some(ref path) = *dir {
        return Ok(PathBuf::from(path));
    }

    // FIXME: Find a way to not rely on the executable being
    // under `<servo source>[/$target_triple]/target/debug`
    // or `<servo source>[/$target_triple]/target/release`.
    let mut path = env::current_exe()?;
    // Follow symlink
    path = path.canonicalize()?;

    while path.pop() {
        path.push("resources");
        if path.is_dir() {
            break;
        }
        path.pop();
        // Check for Resources on mac when using a case sensitive filesystem.
        path.push("Resources");
        if path.is_dir() {
            break;
        }
        path.pop();
    }
    *dir = Some(path.to_str().unwrap().to_owned());
    Ok(path)
}

pub fn read_resource_file<P: AsRef<Path>>(relative_path: P) -> io::Result<Vec<u8>> {
    let mut path = resources_dir_path()?;
    path.push(relative_path);
    let mut file = File::open(&path)?;
    let mut data = Vec::new();
    file.read_to_end(&mut data)?;
    Ok(data)
}
<commit_msg>Auto merge of #18702 - paulrouget:android_res_path, r=Manishearth<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#[cfg(target_os = "android")]
use android_injected_glue;
#[cfg(not(target_os = "android"))]
use std::env;
#[cfg(target_os = "android")]
use std::ffi::CStr;
use std::fs::File;
use std::io::{self, Read};
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};

lazy_static! {
    static ref CMD_RESOURCE_DIR: Arc<Mutex<Option<String>>> = {
        Arc::new(Mutex::new(None))
    };
}

pub fn set_resources_path(path: Option<String>) {
    let mut dir = CMD_RESOURCE_DIR.lock().unwrap();
    *dir = path;
}

#[cfg(target_os = "android")]
#[allow(unsafe_code)]
pub fn resources_dir_path() -> io::Result<PathBuf> {
    let mut dir = CMD_RESOURCE_DIR.lock().unwrap();

    if let Some(ref path) = *dir {
        return Ok(PathBuf::from(path));
    }

    let data_path = unsafe {
        CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath)
    };
    let path = PathBuf::from(data_path.to_str().unwrap());
    *dir = Some(path.to_str().unwrap().to_owned());
    Ok(path)
}

#[cfg(not(target_os = "android"))]
pub fn resources_dir_path() -> io::Result<PathBuf> {
    let mut dir = CMD_RESOURCE_DIR.lock().unwrap();

    if let Some(ref path) = *dir {
        return Ok(PathBuf::from(path));
    }

    // FIXME: Find a way to not rely on the executable being
    // under `<servo source>[/$target_triple]/target/debug`
    // or `<servo source>[/$target_triple]/target/release`.
    let mut path = env::current_exe()?;
    // Follow symlink
    path = path.canonicalize()?;

    while path.pop() {
        path.push("resources");
        if path.is_dir() {
            break;
        }
        path.pop();
        // Check for Resources on mac when using a case sensitive filesystem.
        path.push("Resources");
        if path.is_dir() {
            break;
        }
        path.pop();
    }
    *dir = Some(path.to_str().unwrap().to_owned());
    Ok(path)
}

pub fn read_resource_file<P: AsRef<Path>>(relative_path: P) -> io::Result<Vec<u8>> {
    let mut path = resources_dir_path()?;
    path.push(relative_path);
    let mut file = File::open(&path)?;
    let mut data = Vec::new();
    file.read_to_end(&mut data)?;
    Ok(data)
}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::codemap;
use syntax::ext::base;
use syntax::parse::token;
use syntax::parse::parser::Parser;

use syntax::codemap::Pos;

use html::HtmlState;

/// Trait that means something can be parsed with a configuration.
pub trait Parse<Cfg> {
    /// Parse Self from a Parser and a configuration object.
    fn parse(&mut Parser, Cfg) -> Self;
}

static TEMPLATE:      &'static str = "template";

///
fn parse_start_template(state: &mut HtmlState, parser: &mut Parser) {

    match (
        parser.bump_and_get(),
        parser.bump_and_get(),
        parser.parse_ident(),
        parser.parse_ident(),
        parser.parse_fn_decl(true),
        parser.bump_and_get(),
        parser.bump_and_get()
    ) {
        (
            token::LT,
            token::BINOP(token::PERCENT),
            ident,
            functioname,
            function,
            token::BINOP(token::PERCENT),
            token::GT
        ) => { println!("nice job")},

        (one, two, three, four, five, six, seven) => {
            parser.fatal(format!(
                "Expected `<% template xxx() %>`, found {}{}{}{}{}{}{}",
                one,
                two,
                three,
                four,
                five,
                six,
                seven,
            ).as_slice());
        }
    };
}

fn parse_end_template(state: &mut HtmlState, parser: &mut Parser) {

}

///
///
///
impl<'a, 'b> Parse<(
    codemap::Span,
    &'a mut base::ExtCtxt<'b>,
    Option<ast::Ident>
)> for HtmlState {

    ///
    ///
    ///
    fn parse(
        parser: &mut Parser,
        (_, _, name): (codemap::Span, &'a mut base::ExtCtxt, Option<ast::Ident>)
    ) -> HtmlState {

        let mut state = HtmlState::new(name);

        println!("parser");

        parse_start_template(&mut state, parser);
        parse_end_template(&mut state, parser);
        while parser.token != token::EOF {

            match parser.token {
                token::LT => println!("found <"),
                token::GT => println!("found >"),
                token::LPAREN => println!("found ("),
                token::RPAREN => println!("found )"),
                token::BINOP(token::PERCENT) => println!("found %"),
                token::IDENT(ident, _) => {
                    println!("found ident {}", ident.as_str());
                },
                _ => {
                    parser.fatal("not supported");
                }
            }
            parser.bump();
        }

        state
    }
}
<commit_msg>now we can parse <% end template %><commit_after>use syntax::ast;
use syntax::codemap;
use syntax::ext::base;
use syntax::parse::token;
use syntax::parse::parser::Parser;

use syntax::codemap::Pos;

use html::HtmlState;

/// Trait that means something can be parsed with a configuration.
pub trait Parse<Cfg> {
    /// Parse Self from a Parser and a configuration object.
    fn parse(&mut Parser, Cfg) -> Self;
}

static TEMPLATE:      &'static str = "template";

///
fn parse_start_template(state: &mut HtmlState, parser: &mut Parser) {

    match (
        parser.bump_and_get(),
        parser.bump_and_get(),
        parser.parse_ident(),
        parser.parse_ident(),
        parser.parse_fn_decl(true),
        parser.bump_and_get(),
        parser.bump_and_get()
    ) {
        (
            token::LT,
            token::BINOP(token::PERCENT),
            ident,
            functioname,
            function,
            token::BINOP(token::PERCENT),
            token::GT
        ) => { println!("found template beginning")},

        (one, two, three, four, five, six, seven) => {
            parser.fatal(format!(
                "Expected `<% template xxx() %>`, found {}{}{}{}{}{}{}",
                one,
                two,
                three,
                four,
                five,
                six,
                seven,
            ).as_slice());
        }
    };
}

fn parse_end_template(state: &mut HtmlState, parser: &mut Parser) {
    match (
        parser.bump_and_get(),
        parser.bump_and_get(),
        parser.parse_ident(),
        parser.parse_ident(),
        parser.bump_and_get(),
        parser.bump_and_get()
    ) {
        (
            token::LT,
            token::BINOP(token::PERCENT),
            end,
            template,
            token::BINOP(token::PERCENT),
            token::GT
        ) => { println!("found end template")},

        (one, two, three, four, five, six) => {
            parser.fatal(format!(
                "Expected `<% end template %>`, found {}{}{}{}{}{}",
                one,
                two,
                three,
                four,
                five,
                six
            ).as_slice());
        }
    };

}

///
///
///
impl<'a, 'b> Parse<(
    codemap::Span,
    &'a mut base::ExtCtxt<'b>,
    Option<ast::Ident>
)> for HtmlState {

    ///
    ///
    ///
    fn parse(
        parser: &mut Parser,
        (_, _, name): (codemap::Span, &'a mut base::ExtCtxt, Option<ast::Ident>)
    ) -> HtmlState {

        let mut state = HtmlState::new(name);

        println!("parser");

        parse_start_template(&mut state, parser);
        parse_end_template(&mut state, parser);
        while parser.token != token::EOF {

            match parser.token {
                token::LT => println!("found <"),
                token::GT => println!("found >"),
                token::LPAREN => println!("found ("),
                token::RPAREN => println!("found )"),
                token::BINOP(token::PERCENT) => println!("found %"),
                token::IDENT(ident, _) => {
                    println!("found ident {}", ident.as_str());
                },
                _ => {
                    parser.fatal("not supported");
                }
            }
            parser.bump();
        }

        state
    }
}
<|endoftext|>