<commit_before>//! The `print-cfg` sub-command.
//!
//! Read a series of Cretonne IL files and print their control flow graphs
//! in graphviz format.
use std::fs::File;
use std::io::{Read, Write, stdout};

use CommandResult;
use cretonne::repr::Function;
use cretonne::cfg::ControlFlowGraph;
use cretonne::instructions::InstructionData;
use cton_reader::parser::Parser;

pub fn run(files: Vec<String>) -> CommandResult {
    for (i, f) in files.into_iter().enumerate() {
        if i != 0 {
            println!("");
        }
        try!(print_cfg(f))
    }
    Ok(())
}

struct CFGPrinter<T: Write> {
    level: usize,
    writer: T,
    buffer: String,
}

impl<T: Write> CFGPrinter<T> {
    pub fn new(writer: T) -> CFGPrinter<T> {
        CFGPrinter{level: 0, writer: writer, buffer: String::new()}
    }

    pub fn print(&mut self, func: &Function) -> Result<(), String> {
        self.level = 0;
        self.header(func);
        self.push_indent();
        self.ebb_subgraphs(func);
        let cfg = ControlFlowGraph::new(&func);
        self.cfg_connections(&cfg);
        self.pop_indent();
        self.footer();
        self.write()
    }

    fn write(&mut self) -> Result<(), String> {
        match self.writer.write(self.buffer.as_bytes()) {
            Err(_) => return Err("Write failed!".to_string()),
            _ => (),
        };
        match self.writer.flush() {
            Err(_) => return Err("Flush failed!".to_string()),
            _ => (),
        };
        Ok(())
    }

    fn append(&mut self, s: &str) {
        let mut indent = String::new();
        for _ in 0 .. self.level {
            indent = indent + "    ";
        }
        self.buffer.push_str(&(indent + s));
    }

    fn push_indent(&mut self) {
        self.level += 1;
    }

    fn pop_indent(&mut self) {
        if self.level > 0 {
            self.level -= 1;
        }
    }

    fn open_paren(&mut self) {
        self.append("{");
    }

    fn close_paren(&mut self) {
        self.append("}");
    }

    fn newline(&mut self) {
        self.append("\n");
    }

    fn header(&mut self, func: &Function) {
        self.append(&format!("digraph {} ", func.name));
        self.open_paren();
        self.newline();
        self.push_indent();
        self.append("{rank=min; ebb0}");
        self.pop_indent();
        self.newline();
    }

    fn footer(&mut self) {
        self.close_paren();
        self.newline();
    }

    fn ebb_subgraphs(&mut self, func: &Function) {
        for ebb in func.ebbs_numerically() {
            let inst_data = func.ebb_insts(ebb)
                .filter(|inst| {
                    match func[*inst] {
                        InstructionData::Branch{ ty: _, opcode: _, data: _ } => true,
                        InstructionData::Jump{ ty: _, opcode: _, data: _ } => true,
                        _ => false
                    }
                })
                .map(|inst| {
                    let op = match func[inst] {
                        InstructionData::Branch{ ty: _, opcode, ref data } => {
                            Some((opcode, data.destination))
                        },
                        InstructionData::Jump{ ty: _, opcode, ref data } => {
                            Some((opcode, data.destination))
                        },
                        _ => None
                    };
                    (inst, op)
                })
                .collect::<Vec<_>>();

            let mut insts = vec![format!("{}", ebb)];
            for (inst, data) in inst_data {
                let (op, dest) = data.unwrap();
                insts.push(format!("<{}>{} {}", inst, op, dest));
            }

            self.append(&format!("{} [shape=record, label=\"{}{}{}\"]",
                                ebb, "{", insts.join(" | "), "}"));
            self.newline();
        }
    }

    fn cfg_connections(&mut self, cfg: &ControlFlowGraph) {
        for (ref ebb, ref predecessors) in cfg.iter() {
            for &(parent, inst) in *predecessors {
                self.append(&format!("{}:{} -> {}", parent, inst, ebb));
                self.newline();
            }
        }
    }

}

fn print_cfg(filename: String) -> CommandResult {
    let mut file = try!(File::open(&filename).map_err(|e| format!("{}: {}", filename, e)));
    let mut buffer = String::new();
    try!(file.read_to_string(&mut buffer)
        .map_err(|e| format!("Couldn't read {}: {}", filename, e)));
    let items = try!(Parser::parse(&buffer).map_err(|e| format!("{}: {}", filename, e)));

    let mut cfg_printer = CFGPrinter::new(stdout());
    for (idx, func) in items.into_iter().enumerate() {
        if idx != 0 {
            println!("");
        }

        try!(cfg_printer.print(&func));
    }

    Ok(())
}
<commit_msg>Remove extra newline<commit_after>//! The `print-cfg` sub-command.
//!
//! Read a series of Cretonne IL files and print their control flow graphs
//! in graphviz format.
use std::fs::File;
use std::io::{Read, Write, stdout};

use CommandResult;
use cretonne::repr::Function;
use cretonne::cfg::ControlFlowGraph;
use cretonne::instructions::InstructionData;
use cton_reader::parser::Parser;

pub fn run(files: Vec<String>) -> CommandResult {
    for (i, f) in files.into_iter().enumerate() {
        if i != 0 {
            println!("");
        }
        try!(print_cfg(f))
    }
    Ok(())
}

struct CFGPrinter<T: Write> {
    level: usize,
    writer: T,
    buffer: String,
}

impl<T: Write> CFGPrinter<T> {
    pub fn new(writer: T) -> CFGPrinter<T> {
        CFGPrinter{level: 0, writer: writer, buffer: String::new()}
    }

    pub fn print(&mut self, func: &Function) -> Result<(), String> {
        self.level = 0;
        self.header(func);
        self.push_indent();
        self.ebb_subgraphs(func);
        let cfg = ControlFlowGraph::new(&func);
        self.cfg_connections(&cfg);
        self.pop_indent();
        self.footer();
        self.write()
    }

    fn write(&mut self) -> Result<(), String> {
        match self.writer.write(self.buffer.as_bytes()) {
            Err(_) => return Err("Write failed!".to_string()),
            _ => (),
        };
        match self.writer.flush() {
            Err(_) => return Err("Flush failed!".to_string()),
            _ => (),
        };
        Ok(())
    }

    fn append(&mut self, s: &str) {
        let mut indent = String::new();
        for _ in 0 .. self.level {
            indent = indent + "    ";
        }
        self.buffer.push_str(&(indent + s));
    }

    fn push_indent(&mut self) {
        self.level += 1;
    }

    fn pop_indent(&mut self) {
        if self.level > 0 {
            self.level -= 1;
        }
    }

    fn open_paren(&mut self) {
        self.append("{");
    }

    fn close_paren(&mut self) {
        self.append("}");
    }

    fn newline(&mut self) {
        self.append("\n");
    }

    fn header(&mut self, func: &Function) {
        self.append(&format!("digraph {} ", func.name));
        self.open_paren();
        self.newline();
        self.push_indent();
        self.append("{rank=min; ebb0}");
        self.pop_indent();
        self.newline();
    }

    fn footer(&mut self) {
        self.close_paren();
        self.newline();
    }

    fn ebb_subgraphs(&mut self, func: &Function) {
        for ebb in func.ebbs_numerically() {
            let inst_data = func.ebb_insts(ebb)
                .filter(|inst| {
                    match func[*inst] {
                        InstructionData::Branch{ ty: _, opcode: _, data: _ } => true,
                        InstructionData::Jump{ ty: _, opcode: _, data: _ } => true,
                        _ => false
                    }
                })
                .map(|inst| {
                    let op = match func[inst] {
                        InstructionData::Branch{ ty: _, opcode, ref data } => {
                            Some((opcode, data.destination))
                        },
                        InstructionData::Jump{ ty: _, opcode, ref data } => {
                            Some((opcode, data.destination))
                        },
                        _ => None
                    };
                    (inst, op)
                })
                .collect::<Vec<_>>();

            let mut insts = vec![format!("{}", ebb)];
            for (inst, data) in inst_data {
                let (op, dest) = data.unwrap();
                insts.push(format!("<{}>{} {}", inst, op, dest));
            }

            self.append(&format!("{} [shape=record, label=\"{}{}{}\"]",
                                ebb, "{", insts.join(" | "), "}"));
            self.newline();
        }
    }

    fn cfg_connections(&mut self, cfg: &ControlFlowGraph) {
        for (ref ebb, ref predecessors) in cfg.iter() {
            for &(parent, inst) in *predecessors {
                self.append(&format!("{}:{} -> {}", parent, inst, ebb));
                self.newline();
            }
        }
    }

}

fn print_cfg(filename: String) -> CommandResult {
    let mut file = try!(File::open(&filename).map_err(|e| format!("{}: {}", filename, e)));
    let mut buffer = String::new();
    try!(file.read_to_string(&mut buffer)
        .map_err(|e| format!("Couldn't read {}: {}", filename, e)));
    let items = try!(Parser::parse(&buffer).map_err(|e| format!("{}: {}", filename, e)));

    let mut cfg_printer = CFGPrinter::new(stdout());
    for (idx, func) in items.into_iter().enumerate() {
        if idx != 0 {
            println!("");
        }

        try!(cfg_printer.print(&func));
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::error::Error;

use conduit_middleware;
use conduit::Request;
use conduit_cookie::RequestSession;

use Model;
use db::RequestTransaction;
use super::User;
use util::errors::{CargoResult, Unauthorized, ChainError, std_error};

pub struct Middleware;

impl conduit_middleware::Middleware for Middleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        // Check if the request has a session cookie with a `user_id` property inside
        let id = { req.session().get("user_id").and_then(|s| s.parse().ok()) };

        let user = match id {

            // `user_id` was found on the session
            Some(id) => {

                // Look for a user in the database with the given `user_id`
                match User::find(try!(req.tx().map_err(std_error)), id) {
                    Ok(user) => user,
                    Err(..) => return Ok(()),
                }
            }

            // `user_id` was *not* found on the session
            None => {

                // Look for an `Authorization` header on the request
                let tx = try!(req.tx().map_err(std_error));
                match req.headers().find("Authorization") {
                    Some(headers) => {

                        // Look for a user in the database with a matching API token
                        match User::find_by_api_token(tx, &headers[0]) {
                            Ok(user) => user,
                            Err(..) => return Ok(())
                        }
                    }
                    None => return Ok(())
                }
            }
        };

        // Attach the `User` model from the database to the request
        req.mut_extensions().insert(user);
        Ok(())
    }
}

pub trait RequestUser {
    fn user(&self) -> CargoResult<&User>;
}

impl<'a> RequestUser for Request + 'a {
    fn user(&self) -> CargoResult<&User> {
        self.extensions().find::<User>().chain_error(|| Unauthorized)
    }
}
<commit_msg>user/middleware: Move tx variable further down<commit_after>use std::error::Error;

use conduit_middleware;
use conduit::Request;
use conduit_cookie::RequestSession;

use Model;
use db::RequestTransaction;
use super::User;
use util::errors::{CargoResult, Unauthorized, ChainError, std_error};

pub struct Middleware;

impl conduit_middleware::Middleware for Middleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        // Check if the request has a session cookie with a `user_id` property inside
        let id = { req.session().get("user_id").and_then(|s| s.parse().ok()) };

        let user = match id {

            // `user_id` was found on the session
            Some(id) => {

                // Look for a user in the database with the given `user_id`
                match User::find(try!(req.tx().map_err(std_error)), id) {
                    Ok(user) => user,
                    Err(..) => return Ok(()),
                }
            }

            // `user_id` was *not* found on the session
            None => {

                // Look for an `Authorization` header on the request
                match req.headers().find("Authorization") {
                    Some(headers) => {

                        // Look for a user in the database with a matching API token
                        let tx = try!(req.tx().map_err(std_error));
                        match User::find_by_api_token(tx, &headers[0]) {
                            Ok(user) => user,
                            Err(..) => return Ok(())
                        }
                    }
                    None => return Ok(())
                }
            }
        };

        // Attach the `User` model from the database to the request
        req.mut_extensions().insert(user);
        Ok(())
    }
}

pub trait RequestUser {
    fn user(&self) -> CargoResult<&User>;
}

impl<'a> RequestUser for Request + 'a {
    fn user(&self) -> CargoResult<&User> {
        self.extensions().find::<User>().chain_error(|| Unauthorized)
    }
}
<|endoftext|>


<commit_before>extern crate rosc;

use std::{net, env, process};
use rosc::types::{OscPacket};

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("Usage ./receive IP:PORT");
        process::exit(1);
    }

    let (ip, port) = rosc::utils::parse_ip_and_port(&args[1]).unwrap();
    let sock = net::UdpSocket::bind((ip, port)).unwrap();
    println!("Listening to {}:{}", ip, port);

    let mut buf = [0u8; rosc::decoder::MTP];

    loop {
        match sock.recv_from(&mut buf) {
            Ok((size, addr)) => {
                println!("Received packet with size {} from: {}", size, addr);
                let packet = rosc::decoder::decode(&mut buf).unwrap();
                handle_packet(packet);
            }
            Err(e) => {
                println!("Error receiving from socket: {}", e);
                break;
            }
        }
    }

    drop(sock);
}

fn handle_packet(packet: OscPacket) {
    match packet {
        OscPacket::Message(msg) => {
            println!("OSC address: {}", msg.addr);
            match msg.args {
                Some(args) => {
                    println!("OSC arguments: {:?}", args);
                }
                None => println!("No arguments in message."),
            }
        }
        _ => (),
    }
}
<commit_msg>Rustfmt<commit_after>extern crate rosc;

use std::{net, env, process};
use rosc::types::OscPacket;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("Usage ./receive IP:PORT");
        process::exit(1);
    }

    let (ip, port) = rosc::utils::parse_ip_and_port(&args[1]).unwrap();
    let sock = net::UdpSocket::bind((ip, port)).unwrap();
    println!("Listening to {}:{}", ip, port);

    let mut buf = [0u8; rosc::decoder::MTP];

    loop {
        match sock.recv_from(&mut buf) {
            Ok((size, addr)) => {
                println!("Received packet with size {} from: {}", size, addr);
                let packet = rosc::decoder::decode(&mut buf).unwrap();
                handle_packet(packet);
            }
            Err(e) => {
                println!("Error receiving from socket: {}", e);
                break;
            }
        }
    }

    drop(sock);
}

fn handle_packet(packet: OscPacket) {
    match packet {
        OscPacket::Message(msg) => {
            println!("OSC address: {}", msg.addr);
            match msg.args {
                Some(args) => {
                    println!("OSC arguments: {:?}", args);
                }
                None => println!("No arguments in message."),
            }
        }
        _ => (),
    }
}
<|endoftext|>


<commit_before>/*

Rule 110 is a simple cellular automaton that is universal.

The problem is to find the reverse history from a final state,
up to a limited number of iterations.

*/

extern crate quickbacktrack;

use quickbacktrack::{BackTrackSolver, Puzzle, SolveSettings};

#[derive(Clone)]
pub struct Rule110 {
	pub cells: Vec<Vec<u8>>,
}

impl Rule110 {
    pub fn next(&mut self) -> Vec<u8> {
        let last = self.cells.last().unwrap();
        let n = last.len();
        let mut new_row = vec![0; n];
        for i in 0..n {
            let input = (
                if i > 0 { last[(i + n - 1)%n] } else { 1 },
                last[i],
                if i + 1 < n { last[i + 1] } else { 1 }
            );
            new_row[i] = rule(input);
        }
        new_row
    }

    /// Returns `false` when a contradition is found.
    /// This is checked by checking all affected cells in next step.
    pub fn is_satisfied(&self, pos: [usize; 2], val: u8) -> bool {
        let row = pos[0];
        let col = pos[1] as isize;

        if row + 1 < self.cells.len() {
            // Replace with new value if looking up cell at the location.
            let f = |ind: isize| {
                if ind < 0 { return 1; }
                if ind >= self.cells[row].len() as isize { 1 }
                else if ind == col { val }
                else { self.cells[row][ind as usize] }
            };
            for i in -1..2 {
                // Skip output cells at the edges.
                if col + i <= 0 ||
                   col + i >= self.cells[row].len() as isize {
                    continue;
                }

                let input = (
                    f(col + i - 1),
                    f(col + i),
                    f(col + i + 1),
                );

                let new_value = rule(input);
                let old_value = self.cells[row + 1][(col + i) as usize];
                match (new_value, old_value) {
                    (_, 0) => {}
                    (0, _) => {}
                    (a, b) if a == b => {}
                    (_, _) => return false,
                }
            }
        }

        // Check that previous row yields value.
        if row > 0 {
            let f = |ind: isize| {
                if ind < 0 { return 1; }
                if ind >= self.cells[row - 1].len() as isize { 1 }
                else { self.cells[row - 1][ind as usize] }
            };
            let input = (
                f(col - 1),
                f(col),
                f(col + 1),
            );
            match (rule(input), val) {
                (_, 0) => {}
                (0, _) => {}
                (a, b) if a == b => {}
                (_, _) => return false,
            }
        }

        true
    }

    pub fn possible(&self, pos: [usize; 2]) -> Vec<u8> {
        let mut res = vec![];
        for v in 1..3 {
            if self.is_satisfied(pos, v) {
                res.push(v);
            }
        }
        res
    }

    pub fn find_min_empty(&self) -> Option<[usize; 2]> {
        let mut min = None;
        let mut min_pos = None;
        for i in 0..self.cells.len() {
            for j in 0..self.cells[i].len() {
                if self.cells[i][j] == 0 {
                    let possible = self.possible([i, j]);
                    if min.is_none() || min.unwrap() >= possible.len() {
                        min = Some(possible.len());
                        min_pos = Some([i, j]);
                    }
                }
            }
        }
        return min_pos;
    }
}

/// Rule 110 extended with unknown inputs.
fn rule(state: (u8, u8, u8)) -> u8 {
    match state {
        (2, 2, 2) => 1,
        (2, 2, 1) => 2,
        (2, 1, 2) => 2,
        (2, 1, 1) => 1,
        (1, 2, 2) => 2,
        (1, 2, 1) => 2,
        (1, 1, 2) => 2,
        (1, 1, 1) => 1,

        // 1 unknown.
        (2, 2, 0) => 0,
        (2, 0, 2) => 0,
        (0, 2, 2) => 0,
        (2, 0, 1) => 0,
        (0, 2, 1) => 2,
        (2, 1, 0) => 0,
        (0, 1, 2) => 2,
        (0, 1, 1) => 1,
        (1, 2, 0) => 2,
        (1, 0, 2) => 2,
        (1, 0, 1) => 0,
        (1, 1, 0) => 0,

        // All with 2 unknowns or more has unknown result.
        (_, _, _) => 0,
    }
}

impl Puzzle for Rule110 {
    type Pos = [usize; 2];
    type Val = u8;

    fn solve_simple(&mut self) {}

    fn set(&mut self, pos: [usize; 2], val: u8) {
        self.cells[pos[0]][pos[1]] = val;
    }

    fn is_solved(&self) -> bool {
        for row in &self.cells {
            for col in row {
                if *col == 0 { return false; }
            }
        }
        true
    }

    fn remove(&mut self, other: &Rule110) {
        for i in 0..self.cells.len() {
            for j in 0..self.cells[i].len() {
                if other.cells[i][j] != 0 {
                    self.cells[i][j] = 0;
                }
            }
        }
    }

    fn print(&self) {
        println!("");
        for row in &self.cells {
            for cell in row {
                if *cell == 2 { print!("x"); }
                else if *cell == 1 { print!("_"); }
                else { print!(" "); }
            }
            println!("")
        }
        println!("");
    }
}

fn main() {
    /*
    let mut r = Rule110 {
        cells: vec![
            // _xx__xxxx_xx__x
            vec![1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 2]
        ]
    };
    let next = r.next();
    r.cells.push(next);
    r.print();
    return;
    */

    let x = Rule110 {
        cells: vec![
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
        ]
    };
    // println!("{}", x.is_satisfied([0, 1], 2));

    let settings = SolveSettings::new()
		.solve_simple(false)
		.debug(false)
		.difference(false)
		.sleep_ms(50)
	;
    let solver = BackTrackSolver::new(x, settings);
    let difference = solver.solve(|s| s.find_min_empty(), |s, p| s.possible(p))
		.expect("Expected solution").puzzle;
	println!("Solution:");
	difference.print();
    println!("{}\n{:?}", difference.cells.len(),
        difference.cells[2]);
}

pub fn example1() -> Rule110 {
    Rule110 {
        cells: vec![
            vec![1, 1, 1, 2, 1],
            vec![1, 0, 0, 0, 1],
            vec![1, 0, 0, 0, 1],
            vec![2, 2, 1, 2, 1],
        ]
    }
}

pub fn example2() -> Rule110 {
    Rule110 {
        cells: vec![
            vec![1, 1, 0, 0, 0],
            vec![0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0],
            vec![2, 2, 1, 2, 1],
        ]
    }
}
<commit_msg>Fold edges in "rule_110" example<commit_after>/*

Rule 110 is a simple cellular automaton that is universal.

The problem is to find the reverse history from a final state,
up to a limited number of iterations.

*/

extern crate quickbacktrack;

use quickbacktrack::{BackTrackSolver, Puzzle, SolveSettings};

#[derive(Clone)]
pub struct Rule110 {
	pub cells: Vec<Vec<u8>>,
}

impl Rule110 {
    pub fn next(&mut self) -> Vec<u8> {
        let last = self.cells.last().unwrap();
        let n = last.len();
        let mut new_row = vec![0; n];
        for i in 0..n {
            let input = (
                last[(i + n - 1) % n],
                last[i],
                last[(i + 1) % n]
            );
            new_row[i] = rule(input);
        }
        new_row
    }

    /// Returns `false` when a contradition is found.
    /// This is checked by checking all affected cells in next step.
    pub fn is_satisfied(&self, pos: [usize; 2], val: u8) -> bool {
        let row = pos[0];
        let col = pos[1] as isize;

        let n = self.cells[row].len() as isize;
        if row + 1 < self.cells.len() {
            // Replace with new value if looking up cell at the location.
            let f = |ind: isize| {
                let map_ind = ((col + ind + n) % n) as usize;
                if map_ind == col as usize { val }
                else { self.cells[row][map_ind] }
            };
            // [o o x] [o x o] [x o o]
            for i in -1..2 {
                let input = (
                    f(i - 1),
                    f(i),
                    f(i + 1),
                );

                let col_next = ((col + n + i) % n) as usize;
                let new_value = rule(input);
                let old_value = self.cells[row + 1][col_next];
                match (new_value, old_value) {
                    (_, 0) => {}
                    (0, _) => {}
                    (a, b) if a == b => {}
                    (_, _) => return false,
                }
            }
        }

        // Check that previous row yields value.
        if row > 0 {
            let f = |ind: isize| {
                let map_ind = ((col + ind + n) % n) as usize;
                self.cells[row - 1][map_ind]
            };
            let input = (
                f(-1),
                f(0),
                f(1),
            );
            match (rule(input), val) {
                (_, 0) => {}
                (0, _) => {}
                (a, b) if a == b => {}
                (_, _) => return false,
            }
        }

        true
    }

    pub fn possible(&self, pos: [usize; 2]) -> Vec<u8> {
        let mut res = vec![];
        for v in 1..3 {
            if self.is_satisfied(pos, v) {
                res.push(v);
            }
        }
        res
    }

    pub fn find_min_empty(&self) -> Option<[usize; 2]> {
        let mut min = None;
        let mut min_pos = None;
        for i in 0..self.cells.len() {
            for j in 0..self.cells[i].len() {
                if self.cells[i][j] == 0 {
                    let possible = self.possible([i, j]);
                    if min.is_none() || min.unwrap() >= possible.len() {
                        min = Some(possible.len());
                        min_pos = Some([i, j]);
                    }
                }
            }
        }
        return min_pos;
    }
}

/// Rule 110 extended with unknown inputs.
fn rule(state: (u8, u8, u8)) -> u8 {
    match state {
        (2, 2, 2) => 1,
        (2, 2, 1) => 2,
        (2, 1, 2) => 2,
        (2, 1, 1) => 1,
        (1, 2, 2) => 2,
        (1, 2, 1) => 2,
        (1, 1, 2) => 2,
        (1, 1, 1) => 1,

        // 1 unknown.
        (2, 2, 0) => 0,
        (2, 0, 2) => 0,
        (0, 2, 2) => 0,
        (2, 0, 1) => 0,
        (0, 2, 1) => 2,
        (2, 1, 0) => 0,
        (0, 1, 2) => 2,
        (0, 1, 1) => 1,
        (1, 2, 0) => 2,
        (1, 0, 2) => 2,
        (1, 0, 1) => 0,
        (1, 1, 0) => 0,

        // All with 2 unknowns or more has unknown result.
        (_, _, _) => 0,
    }
}

impl Puzzle for Rule110 {
    type Pos = [usize; 2];
    type Val = u8;

    fn solve_simple(&mut self) {
        loop {
			let mut found_any = false;
			for i in 0..self.cells.len() {
				for j in 0..self.cells[i].len() {
					if self.cells[i][j] != 0 { continue; }
					let possible = self.possible([i, j]);
					if possible.len() == 1 {
						self.cells[i][j] = possible[0];
						found_any = true;
					}
				}
			}
			if !found_any { break; }
		}
    }

    fn set(&mut self, pos: [usize; 2], val: u8) {
        self.cells[pos[0]][pos[1]] = val;
    }

    fn is_solved(&self) -> bool {
        for row in &self.cells {
            for col in row {
                if *col == 0 { return false; }
            }
        }
        true
    }

    fn remove(&mut self, other: &Rule110) {
        for i in 0..self.cells.len() {
            for j in 0..self.cells[i].len() {
                if other.cells[i][j] != 0 {
                    self.cells[i][j] = 0;
                }
            }
        }
    }

    fn print(&self) {
        println!("");
        for row in &self.cells {
            for cell in row {
                if *cell == 2 { print!("o"); }
                else if *cell == 1 { print!("."); }
                else { print!(" "); }
            }
            println!("")
        }
        println!("");
    }
}

fn main() {
    let x = Rule110 {
        cells: vec![
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            vec![1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 2, 0],
        ]
    };

    let settings = SolveSettings::new()
		.solve_simple(true)
		.debug(false)
		.difference(true)
		.sleep_ms(50)
	;
    let solver = BackTrackSolver::new(x, settings);
    let difference = solver.solve(|s| s.find_min_empty(), |s, p| s.possible(p))
		.expect("Expected solution").puzzle;
	println!("Solution:");
	difference.print();
}

pub fn example1() -> Rule110 {
    Rule110 {
        cells: vec![
            vec![1, 1, 1, 2, 1],
            vec![1, 0, 0, 0, 1],
            vec![1, 0, 0, 0, 1],
            vec![2, 2, 1, 2, 1],
        ]
    }
}

pub fn example2() -> Rule110 {
    Rule110 {
        cells: vec![
            vec![1, 1, 0, 0, 0],
            vec![0, 0, 0, 0, 0],
            vec![0, 0, 0, 0, 0],
            vec![2, 2, 1, 2, 1],
        ]
    }
}
<|endoftext|>


<commit_before>// M_2_2_01
//
// Generative Gestaltung – Creative Coding im Web
// ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018
// Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni
// with contributions by Joey Lee and Niels Poldervaart
// Copyright 2018
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * draws a lissajous curve
 *
 * KEYS
 * a                 : toggle oscillation animation
 * 1/2               : frequency x -/+
 * 3/4               : frequency y -/+
 * arrow left/right  : phi -/+
 * s                 : save png
 */
use nannou::prelude::*;

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    point_count: usize,
    freq_x: f32,
    freq_y: f32,
    phi: f32,
    angle: f32,
    x: f32,
    y: f32,
    do_draw_animation: bool,
    margin: f32,
}

fn model(app: &App) -> Model {
    let _window = app
        .new_window()
        .size(600, 600)
        .view(view)
        .key_pressed(key_pressed)
        .build()
        .unwrap();

    Model {
        point_count: 600,
        freq_x: 1.0,
        freq_y: 2.0,
        phi: 90.0,
        angle: 0.0,
        x: 0.0,
        y: 0.0,
        do_draw_animation: true,
        margin: 25.0,
    }
}

fn update(app: &App, model: &mut Model, _update: Update) {
    let t = fmod(app.elapsed_frames() as f32 / model.point_count as f32, 1.0);
    model.angle = map_range(t, 0.0, 1.0, 0.0, TAU);
    model.x = (model.angle * model.freq_x + deg_to_rad(model.phi)).sin();
    model.x *= app.window_rect().w() / 4.0 - model.margin;
    model.y = (model.angle * model.freq_y).sin();
    model.y *= app.window_rect().h() / 4.0 - model.margin;
}

fn view(app: &App, model: &Model, frame: Frame) {
    // Begin drawing
    let draw = app.draw();
    let win = app.window_rect();

    draw.background().color(WHITE);

    let (xs, ys, factor_x, factor_y) = if model.do_draw_animation {
        (
            win.left() + (win.w() * 3.0 / 4.0),
            win.top() - (win.h() * 3.0 / 4.0),
            win.w() / 4.0 - model.margin,
            win.h() / 4.0 - model.margin,
        )
    } else {
        (
            0.0,
            0.0,
            win.w() / 2.0 - model.margin,
            win.h() / 2.0 - model.margin,
        )
    };

    let vertices = (0..=model.point_count)
        .map(|i| {
            let angle = map_range(i, 0, model.point_count, 0.0, TAU);
            let mut x = (angle * model.freq_x + deg_to_rad(model.phi)).sin();
            let mut y = (angle * model.freq_y).sin();
            x *= factor_x;
            y *= factor_y;
            pt2(xs + x, ys + y)
        })
        .enumerate()
        .map(|(_i, p)| {
            let rgba = rgba(0.0, 0.0, 0.0, 1.0);
            (p, rgba)
        });

    // Draw the sine wave.
    draw.polyline().weight(2.0).colored_points(vertices);

    if model.do_draw_animation {
        // draw x oscillator
        let vertices = (0..model.point_count)
            .map(|i| {
                let angle = map_range(i, 0, model.point_count, 0.0, TAU);
                let mut x = (angle * model.freq_x + deg_to_rad(model.phi)).sin();
                x *= win.w() / 4.0 - model.margin;
                let y = -win.h() * 2.0 / 3.0 - model.margin
                    + i as f32 / model.point_count as f32 * (win.h() / 2.0 - 2.0 * model.margin);
                pt2(xs + x, ys - y)
            })
            .enumerate()
            .map(|(_i, p)| {
                let rgba = rgba(0.0, 0.0, 0.0, 1.0);
                (p, rgba)
            });

        draw.polyline().weight(2.0).colored_points(vertices);

        // draw y oscillator
        let vertices = (0..model.point_count)
            .map(|i| {
                let angle = map_range(i, 0, model.point_count, 0.0, TAU);
                let mut y = (angle * model.freq_y).sin();
                y *= win.h() / 4.0 - model.margin;
                let x = -win.w() * 2.0 / 3.0 - model.margin
                    + i as f32 / model.point_count as f32 * (win.w() / 2.0 - 2.0 * model.margin);
                pt2(xs + x, ys - y)
            })
            .enumerate()
            .map(|(_i, p)| {
                let rgba = rgba(0.0, 0.0, 0.0, 1.0);
                (p, rgba)
            });
        draw.polyline().weight(2.0).colored_points(vertices);

        let osc_yx = -win.w() * 2.0 / 3.0 - model.margin
            + fmod(model.angle / TAU, 1.0) * (win.w() / 2.0 - 2.0 * model.margin);
        let osc_xy = -win.h() * 2.0 / 3.0 - model.margin
            + fmod(model.angle / TAU, 1.0) * (win.h() / 2.0 - 2.0 * model.margin);

        let c = rgba(0.0, 0.0, 0.0, 0.5);
        draw.line()
            .start(pt2(xs + model.x, ys - osc_xy))
            .end(pt2(xs + model.x, ys - model.y))
            .color(c);
        draw.line()
            .start(pt2(xs + osc_xy, ys - model.y))
            .end(pt2(xs + model.x, ys - model.y))
            .color(c);

        let c = rgba(0.0, 0.0, 0.0, 1.0);
        draw.ellipse()
            .x_y(xs + model.x, ys - osc_xy)
            .radius(4.0)
            .stroke(gray(1.0))
            .stroke_weight(2.0)
            .color(c);
        draw.ellipse()
            .x_y(xs + osc_yx, ys - model.y)
            .radius(4.0)
            .stroke(gray(1.0))
            .stroke_weight(2.0)
            .color(c);

        draw.ellipse()
            .x_y(xs + model.x, ys - model.y)
            .radius(5.0)
            .stroke(gray(1.0))
            .stroke_weight(2.0)
            .color(c);
    }

    // Write the result of our drawing to the window's frame.
    draw.to_frame(app, &frame).unwrap();
}

fn key_pressed(_app: &App, model: &mut Model, key: Key) {
    match key {
        Key::Key1 => {
            model.freq_x -= 1.0;
        }
        Key::Key2 => {
            model.freq_x += 1.0;
        }
        Key::Key3 => {
            model.freq_y -= 1.0;
        }
        Key::Key4 => {
            model.freq_y += 1.0;
        }
        Key::A => {
            model.do_draw_animation = !model.do_draw_animation;
        }
        Key::Left => {
            model.phi -= 15.0;
        }
        Key::Right => {
            model.phi += 15.0;
        }
        _other_key => {}
    }
    model.freq_x = model.freq_x.max(1.0);
    model.freq_y = model.freq_y.max(1.0);
}
<commit_msg>fixes draw position on m_2_2_01 example<commit_after>// M_2_2_01
//
// Generative Gestaltung – Creative Coding im Web
// ISBN: 978-3-87439-902-9, First Edition, Hermann Schmidt, Mainz, 2018
// Benedikt Groß, Hartmut Bohnacker, Julia Laub, Claudius Lazzeroni
// with contributions by Joey Lee and Niels Poldervaart
// Copyright 2018
//
// http://www.generative-gestaltung.de
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * draws a lissajous curve
 *
 * KEYS
 * a                 : toggle oscillation animation
 * 1/2               : frequency x -/+
 * 3/4               : frequency y -/+
 * arrow left/right  : phi -/+
 * s                 : save png
 */
use nannou::prelude::*;

fn main() {
    nannou::app(model).update(update).run();
}

struct Model {
    point_count: usize,
    freq_x: f32,
    freq_y: f32,
    phi: f32,
    angle: f32,
    x: f32,
    y: f32,
    do_draw_animation: bool,
    margin: f32,
}

fn model(app: &App) -> Model {
    let _window = app
        .new_window()
        .size(600, 600)
        .view(view)
        .key_pressed(key_pressed)
        .build()
        .unwrap();

    Model {
        point_count: 600,
        freq_x: 1.0,
        freq_y: 2.0,
        phi: 90.0,
        angle: 0.0,
        x: 0.0,
        y: 0.0,
        do_draw_animation: true,
        margin: 25.0,
    }
}

fn update(app: &App, model: &mut Model, _update: Update) {
    let t = fmod(app.elapsed_frames() as f32 / model.point_count as f32, 1.0);
    model.angle = map_range(t, 0.0, 1.0, 0.0, TAU);
    model.x = (model.angle * model.freq_x + deg_to_rad(model.phi)).sin();
    model.x *= app.window_rect().w() / 4.0 - model.margin;
    model.y = (model.angle * model.freq_y).sin();
    model.y *= app.window_rect().h() / 4.0 - model.margin;
}

fn view(app: &App, model: &Model, frame: Frame) {
    // Begin drawing
    let draw = app.draw();
    let win = app.window_rect();

    draw.background().color(WHITE);

    let (xs, ys, factor_x, factor_y) = if model.do_draw_animation {
        (
            win.left() + (win.w() * 3.0 / 4.0),
            win.top() - (win.h() * 3.0 / 4.0),
            win.w() / 4.0 - model.margin,
            win.h() / 4.0 - model.margin,
        )
    } else {
        (
            0.0,
            0.0,
            win.w() / 2.0 - model.margin,
            win.h() / 2.0 - model.margin,
        )
    };

    let vertices = (0..=model.point_count)
        .map(|i| {
            let angle = map_range(i, 0, model.point_count, 0.0, TAU);
            let mut x = (angle * model.freq_x + deg_to_rad(model.phi)).sin();
            let mut y = (angle * model.freq_y).sin();
            x *= factor_x;
            y *= factor_y;
            pt2(xs + x, ys - y)
        })
        .enumerate()
        .map(|(_i, p)| {
            let rgba = rgba(0.0, 0.0, 0.0, 1.0);
            (p, rgba)
        });

    // Draw the sine wave.
    draw.polyline().weight(2.0).colored_points(vertices);

    if model.do_draw_animation {
        // draw x oscillator
        let vertices = (0..model.point_count)
            .map(|i| {
                let angle = map_range(i, 0, model.point_count, 0.0, TAU);
                let mut x = (angle * model.freq_x + deg_to_rad(model.phi)).sin();
                x *= win.w() / 4.0 - model.margin;
                let y = -win.h() * 2.0 / 3.0 - model.margin
                    + i as f32 / model.point_count as f32 * (win.h() / 2.0 - 2.0 * model.margin);
                pt2(xs + x, ys - y)
            })
            .enumerate()
            .map(|(_i, p)| {
                let rgba = rgba(0.0, 0.0, 0.0, 1.0);
                (p, rgba)
            });

        draw.polyline().weight(2.0).colored_points(vertices);

        // draw y oscillator
        let vertices = (0..model.point_count)
            .map(|i| {
                let angle = map_range(i, 0, model.point_count, 0.0, TAU);
                let mut y = (angle * model.freq_y).sin();
                y *= win.h() / 4.0 - model.margin;
                let x = -win.w() * 2.0 / 3.0 - model.margin
                    + i as f32 / model.point_count as f32 * (win.w() / 2.0 - 2.0 * model.margin);
                pt2(xs + x, ys - y)
            })
            .enumerate()
            .map(|(_i, p)| {
                let rgba = rgba(0.0, 0.0, 0.0, 1.0);
                (p, rgba)
            });
        draw.polyline().weight(2.0).colored_points(vertices);

        let osc_yx = -win.w() * 2.0 / 3.0 - model.margin
            + fmod(model.angle / TAU, 1.0) * (win.w() / 2.0 - 2.0 * model.margin);
        let osc_xy = -win.h() * 2.0 / 3.0 - model.margin
            + fmod(model.angle / TAU, 1.0) * (win.h() / 2.0 - 2.0 * model.margin);

        let c = rgba(0.0, 0.0, 0.0, 0.5);
        draw.line()
            .start(pt2(xs + model.x, ys - osc_xy))
            .end(pt2(xs + model.x, ys - model.y))
            .color(c);
        draw.line()
            .start(pt2(xs + osc_xy, ys - model.y))
            .end(pt2(xs + model.x, ys - model.y))
            .color(c);

        let c = rgba(0.0, 0.0, 0.0, 1.0);
        draw.ellipse()
            .x_y(xs + model.x, ys - osc_xy)
            .radius(4.0)
            .stroke(gray(1.0))
            .stroke_weight(2.0)
            .color(c);
        draw.ellipse()
            .x_y(xs + osc_yx, ys - model.y)
            .radius(4.0)
            .stroke(gray(1.0))
            .stroke_weight(2.0)
            .color(c);

        draw.ellipse()
            .x_y(xs + model.x, ys - model.y)
            .radius(5.0)
            .stroke(gray(1.0))
            .stroke_weight(2.0)
            .color(c);
    }

    // Write the result of our drawing to the window's frame.
    draw.to_frame(app, &frame).unwrap();
}

fn key_pressed(_app: &App, model: &mut Model, key: Key) {
    match key {
        Key::Key1 => {
            model.freq_x -= 1.0;
        }
        Key::Key2 => {
            model.freq_x += 1.0;
        }
        Key::Key3 => {
            model.freq_y -= 1.0;
        }
        Key::Key4 => {
            model.freq_y += 1.0;
        }
        Key::A => {
            model.do_draw_animation = !model.do_draw_animation;
        }
        Key::Left => {
            model.phi -= 15.0;
        }
        Key::Right => {
            model.phi += 15.0;
        }
        _other_key => {}
    }
    model.freq_x = model.freq_x.max(1.0);
    model.freq_y = model.freq_y.max(1.0);
}
<|endoftext|>


<commit_before>use anyhow::Result;
use std::str::FromStr;

use crate::admin::on_call;

#[derive(Debug, Copy, Clone)]
pub enum EventType {
    Trigger,
    Acknowledge,
    Resolve,
}

impl FromStr for EventType {
    type Err = &'static str;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        match value {
            "trigger" => Ok(EventType::Trigger),
            "acknowledge" => Ok(EventType::Acknowledge),
            "resolve" => Ok(EventType::Resolve),
            _ => Err("Event type must be trigger, acknowledge, or resolve"),
        }
    }
}

#[derive(clap::Parser, Debug)]
#[clap(name = "test-pagerduty", about = "Send a test event to pagerduty")]
pub struct Opts {
    #[clap(possible_values = &["trigger", "acknowledge", "resolve"])]
    event_type: EventType,
    description: Option<String>,
}

pub fn run(opts: Opts) -> Result<()> {
    let event = match opts.event_type {
        EventType::Trigger => on_call::Event::Trigger {
            incident_key: Some("test".into()),
            description: opts.description.unwrap_or_else(|| "Test event".into()),
        },
        EventType::Acknowledge => on_call::Event::Acknowledge {
            incident_key: "test".into(),
            description: opts.description,
        },
        EventType::Resolve => on_call::Event::Resolve {
            incident_key: "test".into(),
            description: opts.description,
        },
    };
    event.send()
}
<commit_msg>clap: Derive possible values for `EventType` argument (#5295)<commit_after>use anyhow::Result;
use std::str::FromStr;

use crate::admin::on_call;

#[derive(Debug, Copy, Clone, clap::ValueEnum)]
pub enum EventType {
    Trigger,
    Acknowledge,
    Resolve,
}

impl FromStr for EventType {
    type Err = &'static str;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        match value {
            "trigger" => Ok(EventType::Trigger),
            "acknowledge" => Ok(EventType::Acknowledge),
            "resolve" => Ok(EventType::Resolve),
            _ => Err("Event type must be trigger, acknowledge, or resolve"),
        }
    }
}

#[derive(clap::Parser, Debug)]
#[clap(name = "test-pagerduty", about = "Send a test event to pagerduty")]
pub struct Opts {
    #[clap(value_enum)]
    event_type: EventType,
    description: Option<String>,
}

pub fn run(opts: Opts) -> Result<()> {
    let event = match opts.event_type {
        EventType::Trigger => on_call::Event::Trigger {
            incident_key: Some("test".into()),
            description: opts.description.unwrap_or_else(|| "Test event".into()),
        },
        EventType::Acknowledge => on_call::Event::Acknowledge {
            incident_key: "test".into(),
            description: opts.description,
        },
        EventType::Resolve => on_call::Event::Resolve {
            incident_key: "test".into(),
            description: opts.description,
        },
    };
    event.send()
}
<|endoftext|>


<commit_before>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use library::*;
use nameutil::crate_name;
use traits::*;

// FIXME: This module needs redundant allocations audit
// TODO: ffi_type computations should be cached

pub fn ffi_type(env: &Env, tid: library::TypeId, c_type: &str) -> Result {
    let (ptr, inner) = rustify_pointers(c_type);
    let res = if ptr.is_empty() {
        if let Some(c_tid) = env.library.find_type(0, c_type) {
            // Fast track plain fundamental types avoiding some checks
            if env.library.type_(c_tid).maybe_ref_as::<Fundamental>().is_some() {
                if let &library::Type::FixedArray(_, size) = env.library.type_(tid) {
                    ffi_inner(env, c_tid, c_type.into())
                        .map_any(|s| format!("[{}; {}]", s, size))
                }
                else {
                    ffi_inner(env, c_tid, c_type.into())
                }
            }
            else { // c_type isn't fundamental
                ffi_inner(env, tid, inner)
            }
        }
        else { // c_type doesn't match any type in the library by name
            ffi_inner(env, tid, inner)
        }
    }
    else { // ptr not empty
        ffi_inner(env, tid, inner)
            .map_any(|s| format!("{} {}", ptr, s))
    };
    trace!("ffi_type({:?}, {}) -> {:?}", tid, c_type, res);
    res
}

fn ffi_inner(env: &Env, tid: library::TypeId, inner: String) -> Result {
    match *env.library.type_(tid) {
        Type::Fundamental(fund) => {
            use library::Fundamental::*;
            let inner = match fund {
                None => "c_void",
                Boolean => "gboolean",
                Int8 => "i8",
                UInt8 => "u8",
                Int16 => "i16",
                UInt16 => "u16",
                Int32 => "i32",
                UInt32 => "u32",
                Int64 => "i64",
                UInt64 => "u64",
                Char => "c_char",
                UChar => "c_char",
                Short => "c_short",
                UShort => "c_ushort",
                Int => "c_int",
                UInt => "c_uint",
                Long => "c_long",
                ULong => "c_ulong",
                Size => "size_t",
                SSize => "ssize_t",
                Float => "c_float",
                Double => "c_double",
                UniChar => "u32",
                Utf8 => "c_char",
                Filename => "c_char",
                Type => "GType",
                Pointer => match &inner[..]  {
                    "void" => "c_void",
                    _ => return Ok(inner),
                },
                Unsupported => return Err(format!("[Unsupported type {}]", inner)),
                VarArgs => panic!("Should not reach here"),
            };
            Ok(inner.into())
        }
        Type::Record(..) | Type::Alias(..) | Type::Function(..) => {
            fix_name(env, tid, &inner)
        }
        Type::CArray(inner_tid) => ffi_inner(env, inner_tid, inner),
        Type::FixedArray(inner_tid, size) => {
            match ffi_inner(env, inner_tid, inner) {
                Ok(s) => Ok(format!("[{}; {}]", s, size)),
                Err(s) => Err(format!("[{}; {}]", s, size)),
            }
        }
        Type::Array(..) | Type::PtrArray(..)
                | Type::List(..) | Type::SList(..) | Type::HashTable(..) => {
            fix_name(env, tid, &inner)
        }
        _ => {
            if let Some(glib_name) = env.library.type_(tid).get_glib_name() {
                if inner != glib_name {
                    let msg = format!("[c:type mismatch {} != {} of {}]", inner, glib_name,
                      env.library.type_(tid).get_name());
                    warn!("{}", msg);
                    Err(msg)
                }
                else {
                    fix_name(env, tid, &inner)
                }
            }
            else {
                let msg = format!("[Missing glib_name of {}, can't match != {}]",
                                  env.library.type_(tid).get_name(), inner);
                warn!("{}", msg);
                Err(msg)
            }
        }
    }
}

fn fix_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::INTERNAL_NAMESPACE {
        match *env.library.type_(type_id) {
            Type::Array(..) | Type::PtrArray(..)
                    | Type::List(..) | Type::SList(..) | Type::HashTable(..) => {
                if Some(MAIN_NAMESPACE) == env.library.find_namespace("GLib") {
                    Ok(name.into())
                }
                else {
                    Ok(format!("{}_ffi::{}", crate_name("GLib"), name))
                }
            }
            _ => Ok(name.into())
        }
    } else {
        let name_with_prefix = if type_id.ns_id == library::MAIN_NAMESPACE {
            name.into()
        } else {
            format!("{}_ffi::{}", fix_namespace(env, type_id), name)
        };
        if env.type_status_sys(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix)
        } else {
            Ok(name_with_prefix)
        }
    }
}

//TODO: check if need to use in non sys codegen
fn fix_namespace(env: &Env, type_id: library::TypeId) -> String {
    crate_name(&env.library.namespace(type_id.ns_id).name)
}

fn rustify_pointers(c_type: &str) -> (String, String) {
    let mut input = c_type.trim();
    let leading_const = input.starts_with("const ");
    if leading_const {
        input = &input[6..];
    }
    let end = [
        input.find(" const"),
        input.find("*const"),
        input.find("*"),
        Some(input.len()),
    ].iter().filter_map(|&x| x).min().unwrap();
    let inner = input[..end].trim().into();

    let mut ptrs: Vec<_> = input[end..].rsplit('*').skip(1)
        .map(|s| if s.contains("const") { "*const" } else { "*mut" }).collect();
    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
        *p = "*const";
    }

    let res = (ptrs.connect(" "), inner);
    trace!("rustify `{}` -> `{}` `{}`", c_type, res.0, res.1);
    res
}

#[cfg(test)]
mod tests {
    use super::rustify_pointers as rustify_ptr;

    fn s(x: &str, y: &str) -> (String, String) {
        (x.into(), y.into())
    }

    #[test]
    fn rustify_pointers() {
        assert_eq!(rustify_ptr("char"), s("", "char"));
        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("const char* const*"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char const * const *"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
    }
}
<commit_msg>ffi_type: allow mismatches when c_type is a parent/prerequisite type<commit_after>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use library::*;
use nameutil::crate_name;
use traits::*;

// FIXME: This module needs redundant allocations audit
// TODO: ffi_type computations should be cached

pub fn ffi_type(env: &Env, tid: library::TypeId, c_type: &str) -> Result {
    let (ptr, inner) = rustify_pointers(c_type);
    let res = if ptr.is_empty() {
        if let Some(c_tid) = env.library.find_type(0, c_type) {
            // Fast track plain fundamental types avoiding some checks
            if env.library.type_(c_tid).maybe_ref_as::<Fundamental>().is_some() {
                if let &library::Type::FixedArray(_, size) = env.library.type_(tid) {
                    ffi_inner(env, c_tid, c_type.into())
                        .map_any(|s| format!("[{}; {}]", s, size))
                }
                else {
                    ffi_inner(env, c_tid, c_type.into())
                }
            }
            else { // c_type isn't fundamental
                ffi_inner(env, tid, inner)
            }
        }
        else { // c_type doesn't match any type in the library by name
            ffi_inner(env, tid, inner)
        }
    }
    else { // ptr not empty
        ffi_inner(env, tid, inner)
            .map_any(|s| format!("{} {}", ptr, s))
    };
    trace!("ffi_type({:?}, {}) -> {:?}", tid, c_type, res);
    res
}

fn ffi_inner(env: &Env, tid: library::TypeId, inner: String) -> Result {
    match *env.library.type_(tid) {
        Type::Fundamental(fund) => {
            use library::Fundamental::*;
            let inner = match fund {
                None => "c_void",
                Boolean => "gboolean",
                Int8 => "i8",
                UInt8 => "u8",
                Int16 => "i16",
                UInt16 => "u16",
                Int32 => "i32",
                UInt32 => "u32",
                Int64 => "i64",
                UInt64 => "u64",
                Char => "c_char",
                UChar => "c_char",
                Short => "c_short",
                UShort => "c_ushort",
                Int => "c_int",
                UInt => "c_uint",
                Long => "c_long",
                ULong => "c_ulong",
                Size => "size_t",
                SSize => "ssize_t",
                Float => "c_float",
                Double => "c_double",
                UniChar => "u32",
                Utf8 => "c_char",
                Filename => "c_char",
                Type => "GType",
                Pointer => match &inner[..]  {
                    "void" => "c_void",
                    _ => return Ok(inner),
                },
                Unsupported => return Err(format!("[Unsupported type {}]", inner)),
                VarArgs => panic!("Should not reach here"),
            };
            Ok(inner.into())
        }
        Type::Record(..) | Type::Alias(..) | Type::Function(..) => {
            fix_name(env, tid, &inner)
        }
        Type::CArray(inner_tid) => ffi_inner(env, inner_tid, inner),
        Type::FixedArray(inner_tid, size) => {
            match ffi_inner(env, inner_tid, inner) {
                Ok(s) => Ok(format!("[{}; {}]", s, size)),
                Err(s) => Err(format!("[{}; {}]", s, size)),
            }
        }
        Type::Array(..) | Type::PtrArray(..)
                | Type::List(..) | Type::SList(..) | Type::HashTable(..) => {
            fix_name(env, tid, &inner)
        }
        _ => {
            if let Some(glib_name) = env.library.type_(tid).get_glib_name() {
                if inner != glib_name && !implements_c_type(&env.library, tid, &inner) {
                    let msg = format!("[c:type mismatch {} != {} of {}]", inner, glib_name,
                      env.library.type_(tid).get_name());
                    warn!("{}", msg);
                    Err(msg)
                }
                else {
                    fix_name(env, tid, &inner)
                }
            }
            else {
                let msg = format!("[Missing glib_name of {}, can't match != {}]",
                                  env.library.type_(tid).get_name(), inner);
                warn!("{}", msg);
                Err(msg)
            }
        }
    }
}

fn fix_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::INTERNAL_NAMESPACE {
        match *env.library.type_(type_id) {
            Type::Array(..) | Type::PtrArray(..)
                    | Type::List(..) | Type::SList(..) | Type::HashTable(..) => {
                if Some(MAIN_NAMESPACE) == env.library.find_namespace("GLib") {
                    Ok(name.into())
                }
                else {
                    Ok(format!("{}_ffi::{}", crate_name("GLib"), name))
                }
            }
            _ => Ok(name.into())
        }
    } else {
        let name_with_prefix = if type_id.ns_id == library::MAIN_NAMESPACE {
            name.into()
        } else {
            format!("{}_ffi::{}", fix_namespace(env, type_id), name)
        };
        if env.type_status_sys(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix)
        } else {
            Ok(name_with_prefix)
        }
    }
}

//TODO: check if need to use in non sys codegen
fn fix_namespace(env: &Env, type_id: library::TypeId) -> String {
    crate_name(&env.library.namespace(type_id.ns_id).name)
}

fn implements_c_type(library: &library::Library, tid: TypeId, c_type: &str) -> bool {
    if let Some(ref klass) = library.type_(tid).maybe_ref_as::<library::Class>() {
        klass.implements.iter().chain(klass.parents.iter())
            .any(|&super_tid| library.type_(super_tid).get_glib_name() == Some(c_type))
    }
    else if let Some(ref iface) = library.type_(tid).maybe_ref_as::<library::Interface>() {
        iface.prereq_parents.iter()
            .any(|&super_tid| library.type_(super_tid).get_glib_name() == Some(c_type))
    }
    else {
        false
    }
}

fn rustify_pointers(c_type: &str) -> (String, String) {
    let mut input = c_type.trim();
    let leading_const = input.starts_with("const ");
    if leading_const {
        input = &input[6..];
    }
    let end = [
        input.find(" const"),
        input.find("*const"),
        input.find("*"),
        Some(input.len()),
    ].iter().filter_map(|&x| x).min().unwrap();
    let inner = input[..end].trim().into();

    let mut ptrs: Vec<_> = input[end..].rsplit('*').skip(1)
        .map(|s| if s.contains("const") { "*const" } else { "*mut" }).collect();
    if let (true, Some(p)) = (leading_const, ptrs.last_mut()) {
        *p = "*const";
    }

    let res = (ptrs.connect(" "), inner);
    trace!("rustify `{}` -> `{}` `{}`", c_type, res.0, res.1);
    res
}

#[cfg(test)]
mod tests {
    use super::rustify_pointers as rustify_ptr;

    fn s(x: &str, y: &str) -> (String, String) {
        (x.into(), y.into())
    }

    #[test]
    fn rustify_pointers() {
        assert_eq!(rustify_ptr("char"), s("", "char"));
        assert_eq!(rustify_ptr("char*"), s("*mut", "char"));
        assert_eq!(rustify_ptr("const char*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const*"), s("*const", "char"));
        assert_eq!(rustify_ptr("char const *"), s("*const", "char"));
        assert_eq!(rustify_ptr(" char * * "), s("*mut *mut", "char"));
        assert_eq!(rustify_ptr("const char**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("char const**"), s("*mut *const", "char"));
        assert_eq!(rustify_ptr("const char* const*"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char const * const *"), s("*const *const", "char"));
        assert_eq!(rustify_ptr("char* const*"), s("*const *mut", "char"));
    }
}
<|endoftext|>


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

use crate::*;
use rand::{Rng, SeedableRng};
use std::{
    io::{self, Write},
    num::NonZeroUsize,
    process,
};
use structopt::{clap::arg_enum, StructOpt};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
use tokio::runtime::Runtime;
// TODO going to remove random seed once cluster deployment supports re-run genesis
use rand::rngs::OsRng;

#[derive(Debug, StructOpt)]
#[structopt(about = "Forged in Fire")]
pub struct Options {
    /// The FILTER string is tested against the name of all tests, and only those tests whose names
    /// contain the filter are run.
    filter: Option<String>,
    #[structopt(long = "exact")]
    /// Exactly match filters rather than by substring
    filter_exact: bool,
    #[structopt(long, default_value = "1", env = "RUST_TEST_THREADS")]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    /// Number of threads used for running tests in parallel
    test_threads: NonZeroUsize,
    #[structopt(short = "q", long)]
    /// Output minimal information
    quiet: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    nocapture: bool,
    #[structopt(long)]
    /// List all tests
    pub list: bool,
    #[structopt(long)]
    /// List or run ignored tests
    ignored: bool,
    #[structopt(long)]
    /// Include ignored tests when listing or running tests
    include_ignored: bool,
    /// Configure formatting of output:
    ///   pretty = Print verbose output;
    ///   terse = Display one character per test;
    ///   (json is unsupported, exists for compatibility with the default test harness)
    #[structopt(long, possible_values = &Format::variants(), default_value, case_insensitive = true)]
    format: Format,
}

impl Options {
    pub fn from_args() -> Self {
        StructOpt::from_args()
    }
}

arg_enum! {
    #[derive(Debug, Eq, PartialEq)]
    pub enum Format {
        Pretty,
        Terse,
        Json,
    }
}

impl Default for Format {
    fn default() -> Self {
        Format::Pretty
    }
}

pub fn forge_main<F: Factory>(tests: ForgeConfig<'_>, factory: F, options: &Options) -> Result<()> {
    let forge = Forge::new(options, tests, factory, EmitJobRequest::default());

    if options.list {
        forge.list()?;

        return Ok(());
    }

    match forge.run() {
        Ok(..) => Ok(()),
        Err(e) => {
            eprintln!("Failed to run tests:\n{}", e);
            process::exit(101); // Exit with a non-zero exit code if tests failed
        }
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum InitialVersion {
    Oldest,
    Newest,
}

pub struct ForgeConfig<'cfg> {
    public_usage_tests: &'cfg [&'cfg dyn PublicUsageTest],
    nft_public_usage_tests: &'cfg [&'cfg dyn NFTPublicUsageTest],
    admin_tests: &'cfg [&'cfg dyn AdminTest],
    network_tests: &'cfg [&'cfg dyn NetworkTest],

    /// The initial number of validators to spawn when the test harness creates a swarm
    initial_validator_count: NonZeroUsize,

    /// The initial version to use when the test harness creates a swarm
    initial_version: InitialVersion,

    /// The initial genesis modules to use when starting a network
    genesis_config: Option<GenesisConfig>,
}

impl<'cfg> ForgeConfig<'cfg> {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn with_public_usage_tests(
        mut self,
        public_usage_tests: &'cfg [&'cfg dyn PublicUsageTest],
    ) -> Self {
        self.public_usage_tests = public_usage_tests;
        self
    }

    pub fn with_nft_public_usage_tests(
        mut self,
        nft_public_usage_tests: &'cfg [&'cfg dyn NFTPublicUsageTest],
    ) -> Self {
        self.nft_public_usage_tests = nft_public_usage_tests;
        self
    }

    pub fn with_admin_tests(mut self, admin_tests: &'cfg [&'cfg dyn AdminTest]) -> Self {
        self.admin_tests = admin_tests;
        self
    }

    pub fn with_network_tests(mut self, network_tests: &'cfg [&'cfg dyn NetworkTest]) -> Self {
        self.network_tests = network_tests;
        self
    }

    pub fn with_initial_validator_count(mut self, initial_validator_count: NonZeroUsize) -> Self {
        self.initial_validator_count = initial_validator_count;
        self
    }

    pub fn with_initial_version(mut self, initial_version: InitialVersion) -> Self {
        self.initial_version = initial_version;
        self
    }

    pub fn with_genesis_modules_bytes(mut self, genesis_modules: Vec<Vec<u8>>) -> Self {
        self.genesis_config = Some(GenesisConfig::Bytes(genesis_modules));
        self
    }

    pub fn with_genesis_modules_path(mut self, genesis_modules: String) -> Self {
        self.genesis_config = Some(GenesisConfig::Path(genesis_modules));
        self
    }

    pub fn number_of_tests(&self) -> usize {
        self.public_usage_tests.len()
            + self.admin_tests.len()
            + self.network_tests.len()
            + self.nft_public_usage_tests.len()
    }

    pub fn all_tests(&self) -> impl Iterator<Item = &'cfg dyn Test> + 'cfg {
        self.public_usage_tests
            .iter()
            .map(|t| t as &dyn Test)
            .chain(self.admin_tests.iter().map(|t| t as &dyn Test))
            .chain(self.network_tests.iter().map(|t| t as &dyn Test))
            .chain(self.nft_public_usage_tests.iter().map(|t| t as &dyn Test))
    }
}

impl<'cfg> Default for ForgeConfig<'cfg> {
    fn default() -> Self {
        Self {
            public_usage_tests: &[],
            nft_public_usage_tests: &[],
            admin_tests: &[],
            network_tests: &[],
            initial_validator_count: NonZeroUsize::new(1).unwrap(),
            initial_version: InitialVersion::Newest,
            genesis_config: None,
        }
    }
}

pub struct Forge<'cfg, F> {
    options: &'cfg Options,
    tests: ForgeConfig<'cfg>,
    factory: F,
    global_job_request: EmitJobRequest,
}

impl<'cfg, F: Factory> Forge<'cfg, F> {
    pub fn new(
        options: &'cfg Options,
        tests: ForgeConfig<'cfg>,
        factory: F,
        global_job_request: EmitJobRequest,
    ) -> Self {
        Self {
            options,
            tests,
            factory,
            global_job_request,
        }
    }

    pub fn list(&self) -> Result<()> {
        for test in self.filter_tests(self.tests.all_tests()) {
            println!("{}: test", test.name());
        }

        if self.options.format == Format::Pretty {
            println!();
            println!(
                "{} tests",
                self.filter_tests(self.tests.all_tests()).count()
            );
        }

        Ok(())
    }

    pub fn initial_version(&self) -> Version {
        let versions = self.factory.versions();
        match self.tests.initial_version {
            InitialVersion::Oldest => versions.min(),
            InitialVersion::Newest => versions.max(),
        }
        .expect("There has to be at least 1 version")
    }

    pub fn genesis_version(&self) -> Version {
        self.factory
            .versions()
            .max()
            .expect("There has to be at least 1 version")
    }

    pub fn run(&self) -> Result<TestReport> {
        let test_count = self.filter_tests(self.tests.all_tests()).count();
        let filtered_out = test_count.saturating_sub(self.tests.all_tests().count());

        let mut report = TestReport::new();
        let mut summary = TestSummary::new(test_count, filtered_out);
        summary.write_starting_msg()?;

        if test_count > 0 {
            println!(
                "Starting Swarm with supported versions: {:?}",
                self.factory
                    .versions()
                    .map(|v| v.to_string())
                    .collect::<Vec<_>>()
            );
            let initial_version = self.initial_version();
            let genesis_version = self.genesis_version();
            let runtime = Runtime::new().unwrap();
            let mut rng = ::rand::rngs::StdRng::from_seed(OsRng.gen());
            let mut swarm = runtime.block_on(self.factory.launch_swarm(
                &mut rng,
                self.tests.initial_validator_count,
                &initial_version,
                &genesis_version,
                self.tests.genesis_config.as_ref(),
            ))?;

            // Run PublicUsageTests
            for test in self.filter_tests(self.tests.public_usage_tests.iter()) {
                let mut public_ctx = PublicUsageContext::new(
                    CoreContext::from_rng(&mut rng),
                    swarm.chain_info().into_public_info(),
                    &mut report,
                );
                let result = run_test(|| test.run(&mut public_ctx));
                summary.handle_result(test.name().to_owned(), result)?;
            }

            // Run NFTPublicUsageTests
            if !self.tests.nft_public_usage_tests.is_empty() {
                runtime.block_on(
                    swarm
                        .chain_info()
                        .into_nft_public_info()
                        .init_nft_environment(),
                )?;
                for test in self.filter_tests(self.tests.nft_public_usage_tests.iter()) {
                    let mut nft_public_ctx = NFTPublicUsageContext::new(
                        CoreContext::from_rng(&mut rng),
                        swarm.chain_info().into_nft_public_info(),
                        &mut report,
                    );
                    let result = run_test(|| runtime.block_on(test.run(&mut nft_public_ctx)));
                    summary.handle_result(test.name().to_owned(), result)?;
                }
            }

            // Run AdminTests
            for test in self.filter_tests(self.tests.admin_tests.iter()) {
                let mut admin_ctx = AdminContext::new(
                    CoreContext::from_rng(&mut rng),
                    swarm.chain_info(),
                    &mut report,
                );
                let result = run_test(|| test.run(&mut admin_ctx));
                summary.handle_result(test.name().to_owned(), result)?;
            }

            for test in self.filter_tests(self.tests.network_tests.iter()) {
                let mut network_ctx = NetworkContext::new(
                    CoreContext::from_rng(&mut rng),
                    &mut *swarm,
                    &mut report,
                    self.global_job_request.clone(),
                );
                let result = run_test(|| test.run(&mut network_ctx));
                summary.handle_result(test.name().to_owned(), result)?;
            }

            report.print_report();

            io::stdout().flush()?;
            io::stderr().flush()?;

            if !summary.success() {
                println!();
                println!("Swarm logs can be found here: {}", swarm.logs_location());
            }
        }

        summary.write_summary()?;

        if summary.success() {
            Ok(report)
        } else {
            Err(anyhow::anyhow!("Tests Failed"))
        }
    }

    fn filter_tests<'a, T: Test, I: Iterator<Item = T> + 'a>(
        &'a self,
        tests: I,
    ) -> impl Iterator<Item = T> + 'a {
        tests
            // Filter by ignored
            .filter(
                move |test| match (self.options.include_ignored, self.options.ignored) {
                    (true, _) => true, // Don't filter anything
                    (false, true) => test.ignored(),
                    (false, false) => !test.ignored(),
                },
            )
            // Filter by test name
            .filter(move |test| {
                if let Some(filter) = &self.options.filter {
                    if self.options.filter_exact {
                        test.name() == &filter[..]
                    } else {
                        test.name().contains(&filter[..])
                    }
                } else {
                    true
                }
            })
    }
}

enum TestResult {
    Ok,
    Failed,
    FailedWithMsg(String),
}

fn run_test<F: FnOnce() -> Result<()>>(f: F) -> TestResult {
    match ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(f)) {
        Ok(Ok(())) => TestResult::Ok,
        Ok(Err(e)) => TestResult::FailedWithMsg(format!("{:?}", e)),
        Err(_) => TestResult::Failed,
    }
}

struct TestSummary {
    stdout: StandardStream,
    total: usize,
    filtered_out: usize,
    passed: usize,
    failed: Vec<String>,
}

impl TestSummary {
    fn new(total: usize, filtered_out: usize) -> Self {
        Self {
            stdout: StandardStream::stdout(ColorChoice::Auto),
            total,
            filtered_out,
            passed: 0,
            failed: Vec::new(),
        }
    }

    fn handle_result(&mut self, name: String, result: TestResult) -> io::Result<()> {
        write!(self.stdout, "test {} ... ", name)?;
        match result {
            TestResult::Ok => {
                self.passed += 1;
                self.write_ok()?;
            }
            TestResult::Failed => {
                self.failed.push(name);
                self.write_failed()?;
            }
            TestResult::FailedWithMsg(msg) => {
                self.failed.push(name);
                self.write_failed()?;
                writeln!(self.stdout)?;

                write!(self.stdout, "Error: {}", msg)?;
            }
        }
        writeln!(self.stdout)?;
        Ok(())
    }

    fn write_ok(&mut self) -> io::Result<()> {
        self.stdout
            .set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
        write!(self.stdout, "ok")?;
        self.stdout.reset()?;
        Ok(())
    }

    fn write_failed(&mut self) -> io::Result<()> {
        self.stdout
            .set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
        write!(self.stdout, "FAILED")?;
        self.stdout.reset()?;
        Ok(())
    }

    fn write_starting_msg(&mut self) -> io::Result<()> {
        writeln!(self.stdout)?;
        writeln!(
            self.stdout,
            "running {} tests",
            self.total - self.filtered_out
        )?;
        Ok(())
    }

    fn write_summary(&mut self) -> io::Result<()> {
        // Print out the failing tests
        if !self.failed.is_empty() {
            writeln!(self.stdout)?;
            writeln!(self.stdout, "failures:")?;
            for name in &self.failed {
                writeln!(self.stdout, "    {}", name)?;
            }
        }

        writeln!(self.stdout)?;
        write!(self.stdout, "test result: ")?;
        if self.failed.is_empty() {
            self.write_ok()?;
        } else {
            self.write_failed()?;
        }
        writeln!(
            self.stdout,
            ". {} passed; {} failed; {} filtered out",
            self.passed,
            self.failed.len(),
            self.filtered_out
        )?;
        writeln!(self.stdout)?;
        Ok(())
    }

    fn success(&self) -> bool {
        self.failed.is_empty()
    }
}
<commit_msg>[forge] accept and ignore "-Z unstable-options" and "--show-output"<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::*;
use rand::{Rng, SeedableRng};
use std::{
    io::{self, Write},
    num::NonZeroUsize,
    process,
};
use structopt::{clap::arg_enum, StructOpt};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
use tokio::runtime::Runtime;
// TODO going to remove random seed once cluster deployment supports re-run genesis
use rand::rngs::OsRng;

#[derive(Debug, StructOpt)]
#[structopt(about = "Forged in Fire")]
pub struct Options {
    /// The FILTER string is tested against the name of all tests, and only those tests whose names
    /// contain the filter are run.
    filter: Option<String>,
    #[structopt(long = "exact")]
    /// Exactly match filters rather than by substring
    filter_exact: bool,
    #[structopt(long, default_value = "1", env = "RUST_TEST_THREADS")]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    /// Number of threads used for running tests in parallel
    test_threads: NonZeroUsize,
    #[structopt(short = "q", long)]
    /// Output minimal information
    quiet: bool,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    nocapture: bool,
    #[structopt(long)]
    /// List all tests
    pub list: bool,
    #[structopt(long)]
    /// List or run ignored tests
    ignored: bool,
    #[structopt(long)]
    /// Include ignored tests when listing or running tests
    include_ignored: bool,
    /// Configure formatting of output:
    ///   pretty = Print verbose output;
    ///   terse = Display one character per test;
    ///   (json is unsupported, exists for compatibility with the default test harness)
    #[structopt(long, possible_values = &Format::variants(), default_value, case_insensitive = true)]
    format: Format,
    #[structopt(short = "Z")]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    /// -Z unstable-options Enable nightly-only flags:
    ///                     unstable-options = Allow use of experimental features
    z_unstable_options: Option<String>,
    #[structopt(long)]
    /// NO-OP: unsupported option, exists for compatibility with the default test harness
    /// Show captured stdout of successful tests
    show_output: bool,
}

impl Options {
    pub fn from_args() -> Self {
        StructOpt::from_args()
    }
}

arg_enum! {
    #[derive(Debug, Eq, PartialEq)]
    pub enum Format {
        Pretty,
        Terse,
        Json,
    }
}

impl Default for Format {
    fn default() -> Self {
        Format::Pretty
    }
}

pub fn forge_main<F: Factory>(tests: ForgeConfig<'_>, factory: F, options: &Options) -> Result<()> {
    let forge = Forge::new(options, tests, factory, EmitJobRequest::default());

    if options.list {
        forge.list()?;

        return Ok(());
    }

    match forge.run() {
        Ok(..) => Ok(()),
        Err(e) => {
            eprintln!("Failed to run tests:\n{}", e);
            process::exit(101); // Exit with a non-zero exit code if tests failed
        }
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum InitialVersion {
    Oldest,
    Newest,
}

pub struct ForgeConfig<'cfg> {
    public_usage_tests: &'cfg [&'cfg dyn PublicUsageTest],
    nft_public_usage_tests: &'cfg [&'cfg dyn NFTPublicUsageTest],
    admin_tests: &'cfg [&'cfg dyn AdminTest],
    network_tests: &'cfg [&'cfg dyn NetworkTest],

    /// The initial number of validators to spawn when the test harness creates a swarm
    initial_validator_count: NonZeroUsize,

    /// The initial version to use when the test harness creates a swarm
    initial_version: InitialVersion,

    /// The initial genesis modules to use when starting a network
    genesis_config: Option<GenesisConfig>,
}

impl<'cfg> ForgeConfig<'cfg> {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn with_public_usage_tests(
        mut self,
        public_usage_tests: &'cfg [&'cfg dyn PublicUsageTest],
    ) -> Self {
        self.public_usage_tests = public_usage_tests;
        self
    }

    pub fn with_nft_public_usage_tests(
        mut self,
        nft_public_usage_tests: &'cfg [&'cfg dyn NFTPublicUsageTest],
    ) -> Self {
        self.nft_public_usage_tests = nft_public_usage_tests;
        self
    }

    pub fn with_admin_tests(mut self, admin_tests: &'cfg [&'cfg dyn AdminTest]) -> Self {
        self.admin_tests = admin_tests;
        self
    }

    pub fn with_network_tests(mut self, network_tests: &'cfg [&'cfg dyn NetworkTest]) -> Self {
        self.network_tests = network_tests;
        self
    }

    pub fn with_initial_validator_count(mut self, initial_validator_count: NonZeroUsize) -> Self {
        self.initial_validator_count = initial_validator_count;
        self
    }

    pub fn with_initial_version(mut self, initial_version: InitialVersion) -> Self {
        self.initial_version = initial_version;
        self
    }

    pub fn with_genesis_modules_bytes(mut self, genesis_modules: Vec<Vec<u8>>) -> Self {
        self.genesis_config = Some(GenesisConfig::Bytes(genesis_modules));
        self
    }

    pub fn with_genesis_modules_path(mut self, genesis_modules: String) -> Self {
        self.genesis_config = Some(GenesisConfig::Path(genesis_modules));
        self
    }

    pub fn number_of_tests(&self) -> usize {
        self.public_usage_tests.len()
            + self.admin_tests.len()
            + self.network_tests.len()
            + self.nft_public_usage_tests.len()
    }

    pub fn all_tests(&self) -> impl Iterator<Item = &'cfg dyn Test> + 'cfg {
        self.public_usage_tests
            .iter()
            .map(|t| t as &dyn Test)
            .chain(self.admin_tests.iter().map(|t| t as &dyn Test))
            .chain(self.network_tests.iter().map(|t| t as &dyn Test))
            .chain(self.nft_public_usage_tests.iter().map(|t| t as &dyn Test))
    }
}

impl<'cfg> Default for ForgeConfig<'cfg> {
    fn default() -> Self {
        Self {
            public_usage_tests: &[],
            nft_public_usage_tests: &[],
            admin_tests: &[],
            network_tests: &[],
            initial_validator_count: NonZeroUsize::new(1).unwrap(),
            initial_version: InitialVersion::Newest,
            genesis_config: None,
        }
    }
}

pub struct Forge<'cfg, F> {
    options: &'cfg Options,
    tests: ForgeConfig<'cfg>,
    factory: F,
    global_job_request: EmitJobRequest,
}

impl<'cfg, F: Factory> Forge<'cfg, F> {
    pub fn new(
        options: &'cfg Options,
        tests: ForgeConfig<'cfg>,
        factory: F,
        global_job_request: EmitJobRequest,
    ) -> Self {
        Self {
            options,
            tests,
            factory,
            global_job_request,
        }
    }

    pub fn list(&self) -> Result<()> {
        for test in self.filter_tests(self.tests.all_tests()) {
            println!("{}: test", test.name());
        }

        if self.options.format == Format::Pretty {
            println!();
            println!(
                "{} tests",
                self.filter_tests(self.tests.all_tests()).count()
            );
        }

        Ok(())
    }

    pub fn initial_version(&self) -> Version {
        let versions = self.factory.versions();
        match self.tests.initial_version {
            InitialVersion::Oldest => versions.min(),
            InitialVersion::Newest => versions.max(),
        }
        .expect("There has to be at least 1 version")
    }

    pub fn genesis_version(&self) -> Version {
        self.factory
            .versions()
            .max()
            .expect("There has to be at least 1 version")
    }

    pub fn run(&self) -> Result<TestReport> {
        let test_count = self.filter_tests(self.tests.all_tests()).count();
        let filtered_out = test_count.saturating_sub(self.tests.all_tests().count());

        let mut report = TestReport::new();
        let mut summary = TestSummary::new(test_count, filtered_out);
        summary.write_starting_msg()?;

        if test_count > 0 {
            println!(
                "Starting Swarm with supported versions: {:?}",
                self.factory
                    .versions()
                    .map(|v| v.to_string())
                    .collect::<Vec<_>>()
            );
            let initial_version = self.initial_version();
            let genesis_version = self.genesis_version();
            let runtime = Runtime::new().unwrap();
            let mut rng = ::rand::rngs::StdRng::from_seed(OsRng.gen());
            let mut swarm = runtime.block_on(self.factory.launch_swarm(
                &mut rng,
                self.tests.initial_validator_count,
                &initial_version,
                &genesis_version,
                self.tests.genesis_config.as_ref(),
            ))?;

            // Run PublicUsageTests
            for test in self.filter_tests(self.tests.public_usage_tests.iter()) {
                let mut public_ctx = PublicUsageContext::new(
                    CoreContext::from_rng(&mut rng),
                    swarm.chain_info().into_public_info(),
                    &mut report,
                );
                let result = run_test(|| test.run(&mut public_ctx));
                summary.handle_result(test.name().to_owned(), result)?;
            }

            // Run NFTPublicUsageTests
            if !self.tests.nft_public_usage_tests.is_empty() {
                runtime.block_on(
                    swarm
                        .chain_info()
                        .into_nft_public_info()
                        .init_nft_environment(),
                )?;
                for test in self.filter_tests(self.tests.nft_public_usage_tests.iter()) {
                    let mut nft_public_ctx = NFTPublicUsageContext::new(
                        CoreContext::from_rng(&mut rng),
                        swarm.chain_info().into_nft_public_info(),
                        &mut report,
                    );
                    let result = run_test(|| runtime.block_on(test.run(&mut nft_public_ctx)));
                    summary.handle_result(test.name().to_owned(), result)?;
                }
            }

            // Run AdminTests
            for test in self.filter_tests(self.tests.admin_tests.iter()) {
                let mut admin_ctx = AdminContext::new(
                    CoreContext::from_rng(&mut rng),
                    swarm.chain_info(),
                    &mut report,
                );
                let result = run_test(|| test.run(&mut admin_ctx));
                summary.handle_result(test.name().to_owned(), result)?;
            }

            for test in self.filter_tests(self.tests.network_tests.iter()) {
                let mut network_ctx = NetworkContext::new(
                    CoreContext::from_rng(&mut rng),
                    &mut *swarm,
                    &mut report,
                    self.global_job_request.clone(),
                );
                let result = run_test(|| test.run(&mut network_ctx));
                summary.handle_result(test.name().to_owned(), result)?;
            }

            report.print_report();

            io::stdout().flush()?;
            io::stderr().flush()?;

            if !summary.success() {
                println!();
                println!("Swarm logs can be found here: {}", swarm.logs_location());
            }
        }

        summary.write_summary()?;

        if summary.success() {
            Ok(report)
        } else {
            Err(anyhow::anyhow!("Tests Failed"))
        }
    }

    fn filter_tests<'a, T: Test, I: Iterator<Item = T> + 'a>(
        &'a self,
        tests: I,
    ) -> impl Iterator<Item = T> + 'a {
        tests
            // Filter by ignored
            .filter(
                move |test| match (self.options.include_ignored, self.options.ignored) {
                    (true, _) => true, // Don't filter anything
                    (false, true) => test.ignored(),
                    (false, false) => !test.ignored(),
                },
            )
            // Filter by test name
            .filter(move |test| {
                if let Some(filter) = &self.options.filter {
                    if self.options.filter_exact {
                        test.name() == &filter[..]
                    } else {
                        test.name().contains(&filter[..])
                    }
                } else {
                    true
                }
            })
    }
}

enum TestResult {
    Ok,
    Failed,
    FailedWithMsg(String),
}

fn run_test<F: FnOnce() -> Result<()>>(f: F) -> TestResult {
    match ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(f)) {
        Ok(Ok(())) => TestResult::Ok,
        Ok(Err(e)) => TestResult::FailedWithMsg(format!("{:?}", e)),
        Err(_) => TestResult::Failed,
    }
}

struct TestSummary {
    stdout: StandardStream,
    total: usize,
    filtered_out: usize,
    passed: usize,
    failed: Vec<String>,
}

impl TestSummary {
    fn new(total: usize, filtered_out: usize) -> Self {
        Self {
            stdout: StandardStream::stdout(ColorChoice::Auto),
            total,
            filtered_out,
            passed: 0,
            failed: Vec::new(),
        }
    }

    fn handle_result(&mut self, name: String, result: TestResult) -> io::Result<()> {
        write!(self.stdout, "test {} ... ", name)?;
        match result {
            TestResult::Ok => {
                self.passed += 1;
                self.write_ok()?;
            }
            TestResult::Failed => {
                self.failed.push(name);
                self.write_failed()?;
            }
            TestResult::FailedWithMsg(msg) => {
                self.failed.push(name);
                self.write_failed()?;
                writeln!(self.stdout)?;

                write!(self.stdout, "Error: {}", msg)?;
            }
        }
        writeln!(self.stdout)?;
        Ok(())
    }

    fn write_ok(&mut self) -> io::Result<()> {
        self.stdout
            .set_color(ColorSpec::new().set_fg(Some(Color::Green)))?;
        write!(self.stdout, "ok")?;
        self.stdout.reset()?;
        Ok(())
    }

    fn write_failed(&mut self) -> io::Result<()> {
        self.stdout
            .set_color(ColorSpec::new().set_fg(Some(Color::Red)))?;
        write!(self.stdout, "FAILED")?;
        self.stdout.reset()?;
        Ok(())
    }

    fn write_starting_msg(&mut self) -> io::Result<()> {
        writeln!(self.stdout)?;
        writeln!(
            self.stdout,
            "running {} tests",
            self.total - self.filtered_out
        )?;
        Ok(())
    }

    fn write_summary(&mut self) -> io::Result<()> {
        // Print out the failing tests
        if !self.failed.is_empty() {
            writeln!(self.stdout)?;
            writeln!(self.stdout, "failures:")?;
            for name in &self.failed {
                writeln!(self.stdout, "    {}", name)?;
            }
        }

        writeln!(self.stdout)?;
        write!(self.stdout, "test result: ")?;
        if self.failed.is_empty() {
            self.write_ok()?;
        } else {
            self.write_failed()?;
        }
        writeln!(
            self.stdout,
            ". {} passed; {} failed; {} filtered out",
            self.passed,
            self.failed.len(),
            self.filtered_out
        )?;
        writeln!(self.stdout)?;
        Ok(())
    }

    fn success(&self) -> bool {
        self.failed.is_empty()
    }
}
<|endoftext|>


<commit_before>struct Gradient {
    start: [i8; 3],
    stop: [i8; 3],
    steps: [i8; 3],
    n: i32,
    total: i32,
}

impl Gradient {
    fn new(start: String, stop: String, steps: i32) -> Gradient {
        Gradient{
            start: [1,2,3],
            stop: [1,2,3],
            steps: [1,2,3],
            n: 0,
            total: 16
        }
    }
}

impl Iterator for Gradient {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        self.n += 1;
        Some("FF00FF".to_string())
    }
}

#[test]
fn it_works() {
  let g = Gradient::new("000000".to_string(), "FFFFFF".to_string(), 16);

  assert_eq!(g.take(2).collect::<Vec<String>>(), vec!["FF00FF".to_string(), "FF00FF".to_string()]);
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>Fleshing out next() method<commit_after>struct Gradient {
    start: [i8; 3],
    stop: [i8; 3],
    steps: [i8; 3],
    n: i32,
    total: i32,
}

impl Gradient {
    fn new(start: String, stop: String, steps: i32) -> Gradient {
        Gradient{
            start: [0,0,0],
            stop: [255,255,255],
            steps: [17,17,17],
            n: 0,
            total: 16
        }
    }
}

impl Iterator for Gradient {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.n {
            n if n == self.total => None,
            n => {
                Some(format!("{:x}{:02x}{:x}", 255, 0, 255))
            }
        }
    }
}

#[test]
fn it_works() {
  let g = Gradient::new("000000".to_string(), "ffffff".to_string(), 16);

  assert_eq!(g.take(2).collect::<Vec<String>>(), vec!["ff00ff".to_string(), "ff00ff".to_string()]);
}

fn main() {
    println!("Hello, world!");
}
<|endoftext|>