<commit_before>use std::io::IoResult;
use std::task::TaskBuilder;

use irc::IrcConnection;
use irc::connection::RawWrite;
use irc::event::IrcEventMessage;

use command_mapper::PluginContainer;

use state::State;
use plugins::{
    DeerPlugin,
    GreedPlugin,
    SeenPlugin,
    RadioPlugin,
    PingPlugin,
    WserverPlugin,
    WhoAmIPlugin,
};

pub struct BotConfig {
    pub server: (String, u16),
    pub command_prefix: String,
    pub nickname: String,
    pub channels: Vec<String>
}

pub struct BotConnection {
    foo: uint
    //
}

impl BotConnection {
    pub fn new(conf: &BotConfig) -> IoResult<BotConnection> {
        let (ref host, port) = conf.server;
        let (mut conn, event_queue) = try!(IrcConnection::new(host.as_slice(), port));

        let mut nick = conf.nickname.clone();
        loop {
            println!("trying nick {}", nick.as_slice());
            match conn.register(nick.as_slice()) {
                Ok(_) => {
                    println!("ok, connected as {}", nick.as_slice());
                    break;
                }
                Err(err) => {
                    if err.should_pick_new_nickname() {
                        nick.push_str("`");
                    } else {
                        panic!("{}", err)
                    }
                }
            };
        }

        for channel in conf.channels.iter() {
            println!("want join: {}", channel);
        }

        for channel in conf.channels.iter() {
            println!("joining {}...", channel);
            match conn.join(channel.as_slice()) {
                Ok(res) => {
                    println!("succeeded in joining {}, got {} nicks",
                        res.channel.as_slice(), res.nicks.len());
                    match conn.who(channel.as_slice()) {
                        Ok(who_res) => {
                            println!("succeeded in WHOing {}, got {} nicks",
                                who_res.channel.as_slice(), who_res.who_records.len());
                        },
                        Err(who_err) => {
                            println!("failed to WHO {}: {}", channel, who_err);
                        }
                    }
                },
                Err(err) => {
                    println!("join error: {}", err);
                    panic!("failed to join channel.. dying");
                }
            }
            println!("END joining {}...", channel);
        }

        let mut state = State::new();

        let mut container = PluginContainer::new(conf.command_prefix.clone());
        container.register(box PingPlugin::new());
        container.register(box GreedPlugin::new());
        container.register(box SeenPlugin::new());
        container.register(box DeerPlugin::new());
        container.register(box RadioPlugin::new());
        container.register(box WserverPlugin::new());
        container.register(box WhoAmIPlugin::new());

        let (tx, rx) = sync_channel(0);
        let cmd_queue = conn.get_command_queue();
        TaskBuilder::new().named("bot-sender").spawn(proc() {
            for message in rx.iter() {
                cmd_queue.send(RawWrite(message));
            }
        });

        for event in event_queue.iter() {
            state.on_event(&event);

            if let IrcEventMessage(ref message) = event {
                // println!("{}", message);
                container.dispatch(&state, &tx, message);
            }
        }

        Ok(BotConnection { foo: 0})
    }
}<commit_msg>Fix deadlock when joining large channels<commit_after>use std::io::IoResult;
use std::task::TaskBuilder;

use irc::IrcConnection;
use irc::connection::RawWrite;
use irc::event::IrcEventMessage;

use command_mapper::PluginContainer;

use state::State;
use plugins::{
    DeerPlugin,
    GreedPlugin,
    SeenPlugin,
    RadioPlugin,
    PingPlugin,
    WserverPlugin,
    WhoAmIPlugin,
};

pub struct BotConfig {
    pub server: (String, u16),
    pub command_prefix: String,
    pub nickname: String,
    pub channels: Vec<String>
}

pub struct BotConnection {
    foo: uint
    //
}

impl BotConnection {
    pub fn new(conf: &BotConfig) -> IoResult<BotConnection> {
        let (ref host, port) = conf.server;
        let (mut conn, event_queue) = try!(IrcConnection::new(host.as_slice(), port));
        let (event_queue_txu, event_queue_rxu) = channel();
        spawn(proc() {
            for event in event_queue.iter() {
                event_queue_txu.send(event);
            }
        });

        let mut nick = conf.nickname.clone();
        loop {
            println!("trying nick {}", nick.as_slice());
            match conn.register(nick.as_slice()) {
                Ok(_) => {
                    println!("ok, connected as {}", nick.as_slice());
                    break;
                }
                Err(err) => {
                    if err.should_pick_new_nickname() {
                        nick.push_str("`");
                    } else {
                        panic!("{}", err)
                    }
                }
            };
        }

        for channel in conf.channels.iter() {
            println!("want join: {}", channel);
        }

        for channel in conf.channels.iter() {
            println!("joining {}...", channel);
            match conn.join(channel.as_slice()) {
                Ok(res) => {
                    println!("succeeded in joining {}, got {} nicks",
                        res.channel.as_slice(), res.nicks.len());
                    match conn.who(channel.as_slice()) {
                        Ok(who_res) => {
                            println!("succeeded in WHOing {}, got {} nicks",
                                who_res.channel.as_slice(), who_res.who_records.len());
                        },
                        Err(who_err) => {
                            println!("failed to WHO {}: {}", channel, who_err);
                        }
                    }
                },
                Err(err) => {
                    println!("join error: {}", err);
                    panic!("failed to join channel.. dying");
                }
            }
            println!("END joining {}...", channel);
        }

        let mut state = State::new();

        let mut container = PluginContainer::new(conf.command_prefix.clone());
        container.register(box PingPlugin::new());
        container.register(box GreedPlugin::new());
        container.register(box SeenPlugin::new());
        container.register(box DeerPlugin::new());
        container.register(box RadioPlugin::new());
        container.register(box WserverPlugin::new());
        container.register(box WhoAmIPlugin::new());

        let (tx, rx) = sync_channel(0);
        let cmd_queue = conn.get_command_queue();
        TaskBuilder::new().named("bot-sender").spawn(proc() {
            for message in rx.iter() {
                cmd_queue.send(RawWrite(message));
            }
        });

        for event in event_queue_rxu.iter() {
            state.on_event(&event);
            if let IrcEventMessage(ref message) = event {
                container.dispatch(&state, &tx, message);
            }
        }

        Ok(BotConnection { foo: 0})
    }
}<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use capstone_rust::capstone;
use super::address::Address;
use super::instruction::Instruction;
use super::disassembler::{Architecture, Disassembler};

impl Instruction for capstone::Instr {
    fn address(&self, _disassembler: &Disassembler) -> Address {
        Address::new(0)
    }

    fn comment(&self, _disassembler: &Disassembler) -> Option<String> {
        None
    }

    fn cycle_count(&self, _disassembler: &Disassembler) -> Option<u32> {
        None
    }

    fn is_call(&self, _disassembler: &Disassembler) -> bool {
        false
    }

    fn is_local_conditional_jump(&self, _disassembler: &Disassembler) -> bool {
        false
    }

    fn is_local_jump(&self, _disassembler: &Disassembler) -> bool {
        false
    }

    fn is_return(&self, _disassembler: &Disassembler) -> bool {
        false
    }

    fn target_address(&self, _disassembler: &Disassembler) -> Option<Address> {
        None
    }
}

impl From<capstone::cs_arch> for Architecture {
    fn from(arch: capstone::cs_arch) -> Self {
        match arch {
            capstone::cs_arch::CS_ARCH_X86 => Architecture::X86,
            _ => panic!("Unexpected arch: {:?}", arch),
        }
    }
}

impl Disassembler for capstone::Capstone {
    fn architecture(&self) -> Architecture {
        self.architecture().into()
    }
}
<commit_msg>Capstone: Return the correct address.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use capstone_rust::capstone;
use super::address::Address;
use super::instruction::Instruction;
use super::disassembler::{Architecture, Disassembler};

impl Instruction for capstone::Instr {
    fn address(&self, _disassembler: &Disassembler) -> Address {
        Address::new(self.address)
    }

    fn comment(&self, _disassembler: &Disassembler) -> Option<String> {
        None
    }

    fn cycle_count(&self, _disassembler: &Disassembler) -> Option<u32> {
        None
    }

    fn is_call(&self, _disassembler: &Disassembler) -> bool {
        false
    }

    fn is_local_conditional_jump(&self, _disassembler: &Disassembler) -> bool {
        false
    }

    fn is_local_jump(&self, _disassembler: &Disassembler) -> bool {
        false
    }

    fn is_return(&self, _disassembler: &Disassembler) -> bool {
        false
    }

    fn target_address(&self, _disassembler: &Disassembler) -> Option<Address> {
        None
    }
}

impl From<capstone::cs_arch> for Architecture {
    fn from(arch: capstone::cs_arch) -> Self {
        match arch {
            capstone::cs_arch::CS_ARCH_X86 => Architecture::X86,
            _ => panic!("Unexpected arch: {:?}", arch),
        }
    }
}

impl Disassembler for capstone::Capstone {
    fn architecture(&self) -> Architecture {
        self.architecture().into()
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::mem;

use bytes::{BufMut, Bytes, BytesMut};
use nom::{self, Needed};
use tokio_util::codec::{Decoder, Encoder};

use imap_proto::types::{Request, RequestId, Response};

#[derive(Default)]
pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let (response, rsp_len) = match imap_proto::Response::from_bytes(buf) {
            Ok((remaining, response)) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                (response, buf.len() - remaining.len())
            }
            Err(nom::Err::Incomplete(Needed::Size(min))) => {
                self.decode_need_message_bytes = min.get();
                return Ok(None);
            }
            Err(nom::Err::Incomplete(_)) => {
                return Ok(None);
            }
            Err(nom::Err::Error(nom::error::Error { code, .. }))
            | Err(nom::Err::Failure(nom::error::Error { code, .. })) => {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{:?} during parsing of {:?}", code, buf),
                ));
            }
        };
        let raw = buf.split_to(rsp_len).freeze();
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl<'a> Encoder<&'a Request<'a>> for ImapCodec {
    type Error = io::Error;
    fn encode(&mut self, msg: &Request, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(&*msg.0);
        dst.put_u8(b' ');
        dst.put_slice(&*msg.1);
        dst.put_slice(b"\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    #[allow(dead_code)] // Contains data that `response` borrows
    raw: Bytes,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    //
    // `raw` is never mutated during the lifetime of `ResponseData`,
    // and `Response` does not not implement any specific drop glue.
    response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done { ref tag, .. } => Some(tag),
            _ => None,
        }
    }

    #[allow(clippy::needless_lifetimes)]
    pub fn parsed<'a>(&'a self) -> &'a Response<'a> {
        &self.response
    }
}
<commit_msg>Remove unused lifetime<commit_after>use std::io;
use std::mem;

use bytes::{BufMut, Bytes, BytesMut};
use nom::{self, Needed};
use tokio_util::codec::{Decoder, Encoder};

use imap_proto::types::{Request, RequestId, Response};

#[derive(Default)]
pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let (response, rsp_len) = match imap_proto::Response::from_bytes(buf) {
            Ok((remaining, response)) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                (response, buf.len() - remaining.len())
            }
            Err(nom::Err::Incomplete(Needed::Size(min))) => {
                self.decode_need_message_bytes = min.get();
                return Ok(None);
            }
            Err(nom::Err::Incomplete(_)) => {
                return Ok(None);
            }
            Err(nom::Err::Error(nom::error::Error { code, .. }))
            | Err(nom::Err::Failure(nom::error::Error { code, .. })) => {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{:?} during parsing of {:?}", code, buf),
                ));
            }
        };
        let raw = buf.split_to(rsp_len).freeze();
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl<'a> Encoder<&'a Request<'a>> for ImapCodec {
    type Error = io::Error;
    fn encode(&mut self, msg: &Request, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(&*msg.0);
        dst.put_u8(b' ');
        dst.put_slice(&*msg.1);
        dst.put_slice(b"\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    #[allow(dead_code)] // Contains data that `response` borrows
    raw: Bytes,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    //
    // `raw` is never mutated during the lifetime of `ResponseData`,
    // and `Response` does not not implement any specific drop glue.
    response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done { ref tag, .. } => Some(tag),
            _ => None,
        }
    }

    #[allow(clippy::needless_lifetimes)]
    pub fn parsed<'a>(&'a self) -> &'a Response<'a> {
        &self.response
    }
}
<|endoftext|>


<commit_before>use raw::{
    jit_type_ubyte,
    jit_type_sbyte,
    jit_type_ushort,
    jit_type_short,
    jit_type_uint,
    jit_type_int,
    jit_type_nuint,
    jit_type_nint,
    jit_type_float32,
    jit_type_float64,
    jit_type_long,
    jit_type_ulong,
    jit_type_sys_bool,
    jit_type_sys_char,
    jit_type_void,

    jit_value_create_long_constant,
    jit_value_create_nint_constant,
    jit_value_create_float64_constant,
    jit_value_create_float32_constant
};
use function::UncompiledFunction;
use function::ABI::CDECL;
use types::get;
use libc::c_long;
use value::Value;
use std::c_str::CString;
use std::mem::transmute;
use types::Type;
use util::NativeRef;
/// A type that can be compiled into a LibJIT representation
pub trait Compile {
    /// Get a JIT representation of this value
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a>;
    /// Get the JIT type repr of the value
    fn jit_type(_:Option<Self>) -> Type;
}
impl Compile for () {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        let ty = get::<()>();
        Value::new(func, ty)
    }
    #[inline(always)]
    fn jit_type(_:Option<()>) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_void)
        }
    }
}
compile_prims!{
    (f64, f64) => (jit_type_float64, jit_value_create_float64_constant),
    (f32, f32) => (jit_type_float32, jit_value_create_float32_constant),
    (int, c_long) => (jit_type_nint, jit_value_create_nint_constant),
    (uint, c_long) => (jit_type_nuint, jit_value_create_nint_constant),
    (i64, c_long) => (jit_type_long, jit_value_create_long_constant),
    (u64, c_long) => (jit_type_ulong, jit_value_create_long_constant),
    (i32, c_long) => (jit_type_int, jit_value_create_nint_constant),
    (u32, c_long) => (jit_type_uint, jit_value_create_nint_constant),
    (i16, c_long) => (jit_type_short, jit_value_create_nint_constant),
    (u16, c_long) => (jit_type_ushort, jit_value_create_nint_constant),
    (i8, c_long) => (jit_type_sbyte, jit_value_create_nint_constant),
    (u8, c_long) => (jit_type_ubyte, jit_value_create_nint_constant),
    (bool, c_long) => (jit_type_sys_bool, jit_value_create_nint_constant),
    (char, c_long) => (jit_type_sys_char, jit_value_create_nint_constant)
}
impl Compile for *const u8 {
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        let c_str = unsafe { CString::new(transmute(*self), false) };
        let ty = get::<&u8>();
        let ptr = Value::new(func, ty);
        let length = c_str.len() + 1u;
        func.insn_store(&ptr, &func.insn_alloca(&func.insn_of(&length)));
        for enum_char in c_str.iter().enumerate() {
            let (pos, ch) = enum_char;
            let char_v = ch.compile(func);
            func.insn_store_relative(&ptr, pos as int, &char_v);
        }
        func.insn_store_relative(&ptr, c_str.len() as int, &func.insn_of(&'\0'));
        ptr
    }
    #[inline(always)]
    fn jit_type(_:Option<*const u8>) -> Type {
        get::<&u8>()
    }
}
impl<T:Compile> Compile for *mut T {
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr(jit_value_create_nint_constant(
                func.as_ptr(),
                get::<&T>().as_ptr(),
                self.to_uint() as c_long
            ))
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<*mut T>) -> Type {
        get::<&T>()
    }
}
impl<'s> Compile for CString {
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        let ty = get::<CString>();
        let val = Value::new(func, ty.clone());
        let string:*const u8 = unsafe { transmute(self.as_ptr()) };
        func.insn_store_relative(&val, 0, &string.compile(func));
        func.insn_store_relative(&val, ty.find_name("is_owned").get_offset() as int, &true.compile(func));
        val
    }
    #[inline]
    fn jit_type(_:Option<CString>) -> Type {
        jit!(struct {
            "ptr": *const u8,
            "is_owned": bool
        })
    }
}
impl<'a> Compile for &'a str {
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        let str_ptr = {
            let ty = get::<*const u8>();
            let ptr = Value::new(func, ty);
            func.insn_store(&ptr, &func.insn_alloca(&func.insn_of(&self.len())));
            for enum_char in self.bytes().enumerate() {
                let (pos, ch) = enum_char;
                let char_v = ch.compile(func);
                func.insn_store_relative(&ptr, pos as int, &char_v);
            }
            ptr
        };
        let ty = get::<&'a str>();
        let val = Value::new(func, ty.clone());
        func.insn_store_relative(&val, 0, &str_ptr);
        func.insn_store_relative(&val, ty.find_name("len").get_offset() as int, &self.len().compile(func));
        val
    }
    #[inline]
    fn jit_type(_:Option<&'a str>) -> Type {
        jit!(struct {
            "ptr": *const u8,
            "len": uint
        })
    }
}
impl<'a> Compile for String {
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        let str_ptr = {
            let ty = get::<*const u8>();
            let ptr = Value::new(func, ty);
            func.insn_store(&ptr, &func.insn_alloca(&func.insn_of(&self.len())));
            for (pos, ch) in self.as_slice().bytes().enumerate() {
                let char_v = ch.compile(func);
                func.insn_store_relative(&ptr, pos as int, &char_v);
            }
            ptr
        };
        let ty = get::<String>();
        let val = Value::new(func, ty.clone());
        let length = self.len().compile(func);
        func.insn_store_relative(&val, 0, &length);
        func.insn_store_relative(&val, ty.clone().find_name("cap").get_offset() as int, &length);
        func.insn_store_relative(&val, ty.find_name("ptr").get_offset() as int, &str_ptr);
        val
    }
    #[inline]
    fn jit_type(_:Option<String>) -> Type {
        jit!(struct {
            "len": uint,
            "cap": uint,
            "ptr": &u8
        })
    }
}
impl<'a, T:Compile> Compile for Vec<T> {
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        let vec_ptr = {
            let ty = get::<&T>();
            let inner_ty = get::<T>();
            let ptr = Value::new(func, ty);
            let ptr_size = self.len() * inner_ty.get_size();
            let ptr_size = func.insn_of(&ptr_size);
            func.insn_store(&ptr, &func.insn_alloca(&ptr_size));
            for (pos, val) in self.iter().enumerate() {
                let val_v = val.compile(func);
                func.insn_store_relative(&ptr, pos as int, &val_v);
            }
            ptr
        };
        let ty = get::<String>();
        let val = Value::new(func, ty.clone());
        let length = func.insn_of(&self.len());
        func.insn_store_relative(&val, 0, &length);
        func.insn_store_relative(&val, ty.clone().find_name("cap").get_offset() as int, &length);
        func.insn_store_relative(&val, ty.find_name("ptr").get_offset() as int, &vec_ptr);
        val
    }
    #[inline]
    fn jit_type(_:Option<Vec<T>>) -> Type {
        jit!(struct {
            "len": uint,
            "cap": uint,
            "ptr": &T
        })
    }
}
impl<'a, T:Compile> Compile for &'a T {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr(jit_value_create_nint_constant(
                func.as_ptr(),
                get::<T>().as_ptr(),
                (*self as *const T).to_uint() as c_long
            ))
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<&'a T>) -> Type {
        Type::create_pointer(get::<T>())
    }
}
compile_func!(fn() -> R, fn() -> R)
compile_func!(fn(A) -> R, fn(A) -> R)
compile_func!(fn(A, B) -> R, fn(A, B) -> R)
compile_func!(fn(A, B, C) -> R, fn(A, B, C) -> R)
compile_func!(fn(A, B, C, D) -> R, fn(A, B, C, D) -> R)<commit_msg>Be more specific with lifetime in `Compile` trait<commit_after>use raw::{
    jit_type_ubyte,
    jit_type_sbyte,
    jit_type_ushort,
    jit_type_short,
    jit_type_uint,
    jit_type_int,
    jit_type_nuint,
    jit_type_nint,
    jit_type_float32,
    jit_type_float64,
    jit_type_long,
    jit_type_ulong,
    jit_type_sys_bool,
    jit_type_sys_char,
    jit_type_void,

    jit_value_create_long_constant,
    jit_value_create_nint_constant,
    jit_value_create_float64_constant,
    jit_value_create_float32_constant
};
use function::UncompiledFunction;
use function::ABI::CDECL;
use types::get;
use libc::c_long;
use value::Value;
use std::c_str::CString;
use std::mem::transmute;
use types::Type;
use util::NativeRef;
/// A type that can be compiled into a LibJIT representation
pub trait Compile {
    /// Get a JIT representation of this value
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a>;
    /// Get the JIT type repr of the value
    fn jit_type(_:Option<Self>) -> Type;
}
impl Compile for () {
    #[inline(always)]
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
        let ty = get::<()>();
        Value::new(func, ty)
    }
    #[inline(always)]
    fn jit_type(_:Option<()>) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_void)
        }
    }
}
compile_prims!{
    (f64, f64) => (jit_type_float64, jit_value_create_float64_constant),
    (f32, f32) => (jit_type_float32, jit_value_create_float32_constant),
    (int, c_long) => (jit_type_nint, jit_value_create_nint_constant),
    (uint, c_long) => (jit_type_nuint, jit_value_create_nint_constant),
    (i64, c_long) => (jit_type_long, jit_value_create_long_constant),
    (u64, c_long) => (jit_type_ulong, jit_value_create_long_constant),
    (i32, c_long) => (jit_type_int, jit_value_create_nint_constant),
    (u32, c_long) => (jit_type_uint, jit_value_create_nint_constant),
    (i16, c_long) => (jit_type_short, jit_value_create_nint_constant),
    (u16, c_long) => (jit_type_ushort, jit_value_create_nint_constant),
    (i8, c_long) => (jit_type_sbyte, jit_value_create_nint_constant),
    (u8, c_long) => (jit_type_ubyte, jit_value_create_nint_constant),
    (bool, c_long) => (jit_type_sys_bool, jit_value_create_nint_constant),
    (char, c_long) => (jit_type_sys_char, jit_value_create_nint_constant)
}
impl Compile for *const u8 {
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
        let c_str = unsafe { CString::new(transmute(*self), false) };
        let ty = get::<&u8>();
        let ptr = Value::new(func, ty);
        let length = c_str.len() + 1u;
        func.insn_store(&ptr, &func.insn_alloca(&func.insn_of(&length)));
        for enum_char in c_str.iter().enumerate() {
            let (pos, ch) = enum_char;
            let char_v = ch.compile(func);
            func.insn_store_relative(&ptr, pos as int, &char_v);
        }
        func.insn_store_relative(&ptr, c_str.len() as int, &func.insn_of(&'\0'));
        ptr
    }
    #[inline(always)]
    fn jit_type(_:Option<*const u8>) -> Type {
        get::<&u8>()
    }
}
impl<T:Compile> Compile for *mut T {
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr(jit_value_create_nint_constant(
                func.as_ptr(),
                get::<&T>().as_ptr(),
                self.to_uint() as c_long
            ))
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<*mut T>) -> Type {
        get::<&T>()
    }
}
impl<'s> Compile for CString {
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
        let ty = get::<CString>();
        let val = Value::new(func, ty.clone());
        let string:*const u8 = unsafe { transmute(self.as_ptr()) };
        func.insn_store_relative(&val, 0, &string.compile(func));
        func.insn_store_relative(&val, ty.find_name("is_owned").get_offset() as int, &true.compile(func));
        val
    }
    #[inline]
    fn jit_type(_:Option<CString>) -> Type {
        jit!(struct {
            "ptr": *const u8,
            "is_owned": bool
        })
    }
}
impl<'a> Compile for &'a str {
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
        let str_ptr = {
            let ty = get::<*const u8>();
            let ptr = Value::new(func, ty);
            func.insn_store(&ptr, &func.insn_alloca(&func.insn_of(&self.len())));
            for enum_char in self.bytes().enumerate() {
                let (pos, ch) = enum_char;
                let char_v = ch.compile(func);
                func.insn_store_relative(&ptr, pos as int, &char_v);
            }
            ptr
        };
        let ty = get::<&'a str>();
        let val = Value::new(func, ty.clone());
        func.insn_store_relative(&val, 0, &str_ptr);
        func.insn_store_relative(&val, ty.find_name("len").get_offset() as int, &self.len().compile(func));
        val
    }
    #[inline]
    fn jit_type(_:Option<&'a str>) -> Type {
        jit!(struct {
            "ptr": *const u8,
            "len": uint
        })
    }
}
impl<'a> Compile for String {
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
        let str_ptr = {
            let ty = get::<*const u8>();
            let ptr = Value::new(func, ty);
            func.insn_store(&ptr, &func.insn_alloca(&func.insn_of(&self.len())));
            for (pos, ch) in self.as_slice().bytes().enumerate() {
                let char_v = ch.compile(func);
                func.insn_store_relative(&ptr, pos as int, &char_v);
            }
            ptr
        };
        let ty = get::<String>();
        let val = Value::new(func, ty.clone());
        let length = self.len().compile(func);
        func.insn_store_relative(&val, 0, &length);
        func.insn_store_relative(&val, ty.clone().find_name("cap").get_offset() as int, &length);
        func.insn_store_relative(&val, ty.find_name("ptr").get_offset() as int, &str_ptr);
        val
    }
    #[inline]
    fn jit_type(_:Option<String>) -> Type {
        jit!(struct {
            "len": uint,
            "cap": uint,
            "ptr": &u8
        })
    }
}
impl<'a, T:Compile> Compile for Vec<T> {
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
        let vec_ptr = {
            let ty = get::<&T>();
            let inner_ty = get::<T>();
            let ptr = Value::new(func, ty);
            let ptr_size = self.len() * inner_ty.get_size();
            let ptr_size = func.insn_of(&ptr_size);
            func.insn_store(&ptr, &func.insn_alloca(&ptr_size));
            for (pos, val) in self.iter().enumerate() {
                let val_v = val.compile(func);
                func.insn_store_relative(&ptr, pos as int, &val_v);
            }
            ptr
        };
        let ty = get::<String>();
        let val = Value::new(func, ty.clone());
        let length = func.insn_of(&self.len());
        func.insn_store_relative(&val, 0, &length);
        func.insn_store_relative(&val, ty.clone().find_name("cap").get_offset() as int, &length);
        func.insn_store_relative(&val, ty.find_name("ptr").get_offset() as int, &vec_ptr);
        val
    }
    #[inline]
    fn jit_type(_:Option<Vec<T>>) -> Type {
        jit!(struct {
            "len": uint,
            "cap": uint,
            "ptr": &T
        })
    }
}
impl<'a, T:Compile> Compile for &'a T {
    #[inline(always)]
    fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr(jit_value_create_nint_constant(
                func.as_ptr(),
                get::<T>().as_ptr(),
                (*self as *const T).to_uint() as c_long
            ))
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<&'a T>) -> Type {
        Type::create_pointer(get::<T>())
    }
}
compile_func!(fn() -> R, fn() -> R)
compile_func!(fn(A) -> R, fn(A) -> R)
compile_func!(fn(A, B) -> R, fn(A, B) -> R)
compile_func!(fn(A, B, C) -> R, fn(A, B, C) -> R)
compile_func!(fn(A, B, C, D) -> R, fn(A, B, C, D) -> R)<|endoftext|>


<commit_before>//! Transformation of complex data.

// The implementation is based on:
// http://www.librow.com/articles/article-10

use number::c64;

/// Perform the forward transform.
///
/// The number of points should be a power of two.
pub fn forward(data: &mut [c64]) {
    let n = power_of_two!(data);
    rearrange(data, n);
    perform(data, n, false);
}

/// Perform the backward transform.
///
/// The number of points should be a power of two.
pub fn backward(data: &mut [c64]) {
    let n = power_of_two!(data);
    rearrange(data, n);
    perform(data, n, true);
}

/// Perform the inverse transform.
///
/// The number of points should be a power of two.
pub fn inverse(data: &mut [c64]) {
    let n = power_of_two!(data);
    rearrange(data, n);
    perform(data, n, true);
    scale(data, n);
}

fn rearrange(data: &mut [c64], n: usize) {
    let mut j = 0;
    for i in 0..n {
        if j > i {
            data.swap(i, j);
        }
        let mut mask = n >> 1;
        while j & mask != 0 {
            j &= !mask;
            mask >>= 1;
        }
        j |= mask;
    }
}

fn perform(data: &mut [c64], n: usize, inverse: bool) {
    let sign = if inverse { 1.0 } else { -1.0 };
    let mut step = 1;
    while step < n {
        let jump = step << 1;
        let (multiplier, mut factor) = {
            use std::f64::consts::PI;
            let theta = sign * PI / step as f64;
            let sine = (0.5 * theta).sin();
            (c64(-2.0 * sine * sine, theta.sin()), c64(1.0, 0.0))
        };
        for mut i in 0..step {
            while i < n {
                let j = i + step;
                let product = factor * data[j];
                data[j] = data[i] - product;
                data[i] = data[i] + product;
                i += jump;
            }
            factor = multiplier * factor + factor;
        }
        step <<= 1;
    }
}

fn scale(data: &mut [c64], n: usize) {
    let factor = 1.0 / n as f64;
    for i in 0..n {
        data[i] = data[i] * factor;
    }
}
<commit_msg>Rename perform to transform<commit_after>//! Transformation of complex data.

// The implementation is based on:
// http://www.librow.com/articles/article-10

use number::c64;

/// Perform the forward transform.
///
/// The number of points should be a power of two.
pub fn forward(data: &mut [c64]) {
    let n = power_of_two!(data);
    rearrange(data, n);
    transform(data, n, false);
}

/// Perform the backward transform.
///
/// The number of points should be a power of two.
pub fn backward(data: &mut [c64]) {
    let n = power_of_two!(data);
    rearrange(data, n);
    transform(data, n, true);
}

/// Perform the inverse transform.
///
/// The number of points should be a power of two.
pub fn inverse(data: &mut [c64]) {
    let n = power_of_two!(data);
    rearrange(data, n);
    transform(data, n, true);
    scale(data, n);
}

fn rearrange(data: &mut [c64], n: usize) {
    let mut j = 0;
    for i in 0..n {
        if j > i {
            data.swap(i, j);
        }
        let mut mask = n >> 1;
        while j & mask != 0 {
            j &= !mask;
            mask >>= 1;
        }
        j |= mask;
    }
}

fn transform(data: &mut [c64], n: usize, inverse: bool) {
    let sign = if inverse { 1.0 } else { -1.0 };
    let mut step = 1;
    while step < n {
        let jump = step << 1;
        let (multiplier, mut factor) = {
            use std::f64::consts::PI;
            let theta = sign * PI / step as f64;
            let sine = (0.5 * theta).sin();
            (c64(-2.0 * sine * sine, theta.sin()), c64(1.0, 0.0))
        };
        for mut i in 0..step {
            while i < n {
                let j = i + step;
                let product = factor * data[j];
                data[j] = data[i] - product;
                data[i] = data[i] + product;
                i += jump;
            }
            factor = multiplier * factor + factor;
        }
        step <<= 1;
    }
}

fn scale(data: &mut [c64], n: usize) {
    let factor = 1.0 / n as f64;
    for i in 0..n {
        data[i] = data[i] * factor;
    }
}
<|endoftext|>


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

#![forbid(unsafe_code)]
use std::{cmp::min, env};

use crate::{
    cluster::Cluster,
    experiments::{
        CompatiblityTestParams, CpuFlamegraphParams, Experiment, ExperimentParam,
        PerformanceBenchmarkParams, PerformanceBenchmarkThreeRegionSimulationParams,
        RebootRandomValidatorsParams, RecoveryTimeParams, TwinValidatorsParams,
    },
};
use anyhow::{format_err, Result};

pub struct ExperimentSuite {
    pub experiments: Vec<Box<dyn Experiment>>,
}

impl ExperimentSuite {
    fn new_pre_release(cluster: &Cluster) -> Self {
        let mut experiments: Vec<Box<dyn Experiment>> = vec![];
        if env::var("RECOVERY_EXP").is_ok() {
            experiments.push(Box::new(
                RecoveryTimeParams {
                    num_accounts_to_mint: 100_000,
                }
                .build(cluster),
            ));
        }
        let count = min(3, cluster.validator_instances().len() / 3);
        // Reboot different sets of 3 validators *100 times
        for _ in 0..10 {
            let b = Box::new(RebootRandomValidatorsParams::new(count, 0).build(cluster));
            experiments.push(b);
        }
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(0).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(10).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkThreeRegionSimulationParams {}.build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_fixed_tps(0, 10).build(cluster),
        ));
        experiments.push(Box::new(TwinValidatorsParams { pair: 1 }.build(cluster)));
        experiments.push(Box::new(
            CpuFlamegraphParams { duration_secs: 60 }.build(cluster),
        ));
        Self { experiments }
    }

    fn new_perf_suite(cluster: &Cluster) -> Self {
        let mut experiments: Vec<Box<dyn Experiment>> = vec![];
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(0).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(10).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_fixed_tps(0, 10).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkThreeRegionSimulationParams {}.build(cluster),
        ));
        Self { experiments }
    }

    fn new_land_blocking_suite(cluster: &Cluster) -> Self {
        let mut experiments: Vec<Box<dyn Experiment>> = vec![];
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(0).build(cluster),
        ));
        Self { experiments }
    }

    fn new_land_blocking_compat_suite(cluster: &Cluster) -> Result<Self> {
        let count: usize = match env::var("BATCH_SIZE") {
            Ok(val) => val
                .parse()
                .map_err(|e| format_err!("Failed to parse BATCH_SIZE {}: {}", val, e))?,
            Err(_) => cluster.validator_instances().len() / 2,
        };
        let updated_image_tag = env::var("UPDATE_TO_TAG")
            .map_err(|_| format_err!("Expected environment variable UPDATE_TO_TAG"))?;
        let mut experiments: Vec<Box<dyn Experiment>> = vec![];
        experiments.push(Box::new(
            CompatiblityTestParams {
                count,
                updated_image_tag,
            }
            .build(cluster),
        ));
        experiments.extend(Self::new_land_blocking_suite(cluster).experiments);
        Ok(Self { experiments })
    }

    pub fn new_by_name(cluster: &Cluster, name: &str) -> Result<Self> {
        match name {
            "perf" => Ok(Self::new_perf_suite(cluster)),
            "pre_release" => Ok(Self::new_pre_release(cluster)),
            "land_blocking" => Ok(Self::new_land_blocking_suite(cluster)),
            "land_blocking_compat" => Self::new_land_blocking_compat_suite(cluster),
            other => Err(format_err!("Unknown suite: {}", other)),
        }
    }
}
<commit_msg>[cluster-test] comment twin test out to unblock CI during investigation<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]
use std::{cmp::min, env};

use crate::{
    cluster::Cluster,
    experiments::{
        CompatiblityTestParams, CpuFlamegraphParams, Experiment, ExperimentParam,
        PerformanceBenchmarkParams, PerformanceBenchmarkThreeRegionSimulationParams,
        RebootRandomValidatorsParams, RecoveryTimeParams,
    },
};
use anyhow::{format_err, Result};

pub struct ExperimentSuite {
    pub experiments: Vec<Box<dyn Experiment>>,
}

impl ExperimentSuite {
    fn new_pre_release(cluster: &Cluster) -> Self {
        let mut experiments: Vec<Box<dyn Experiment>> = vec![];
        if env::var("RECOVERY_EXP").is_ok() {
            experiments.push(Box::new(
                RecoveryTimeParams {
                    num_accounts_to_mint: 100_000,
                }
                .build(cluster),
            ));
        }
        let count = min(3, cluster.validator_instances().len() / 3);
        // Reboot different sets of 3 validators *100 times
        for _ in 0..10 {
            let b = Box::new(RebootRandomValidatorsParams::new(count, 0).build(cluster));
            experiments.push(b);
        }
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(0).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(10).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkThreeRegionSimulationParams {}.build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_fixed_tps(0, 10).build(cluster),
        ));
        // TODO, comment it out to unblock CI during investigation
        // experiments.push(Box::new(TwinValidatorsParams { pair: 1 }.build(cluster)));
        experiments.push(Box::new(
            CpuFlamegraphParams { duration_secs: 60 }.build(cluster),
        ));
        Self { experiments }
    }

    fn new_perf_suite(cluster: &Cluster) -> Self {
        let mut experiments: Vec<Box<dyn Experiment>> = vec![];
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(0).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(10).build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkThreeRegionSimulationParams {}.build(cluster),
        ));
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_fixed_tps(0, 10).build(cluster),
        ));
        Self { experiments }
    }

    fn new_land_blocking_suite(cluster: &Cluster) -> Self {
        let mut experiments: Vec<Box<dyn Experiment>> = vec![];
        experiments.push(Box::new(
            PerformanceBenchmarkParams::new_nodes_down(0).build(cluster),
        ));
        Self { experiments }
    }

    fn new_land_blocking_compat_suite(cluster: &Cluster) -> Result<Self> {
        let count: usize = match env::var("BATCH_SIZE") {
            Ok(val) => val
                .parse()
                .map_err(|e| format_err!("Failed to parse BATCH_SIZE {}: {}", val, e))?,
            Err(_) => cluster.validator_instances().len() / 2,
        };
        let updated_image_tag = env::var("UPDATE_TO_TAG")
            .map_err(|_| format_err!("Expected environment variable UPDATE_TO_TAG"))?;
        let mut experiments: Vec<Box<dyn Experiment>> = vec![];
        experiments.push(Box::new(
            CompatiblityTestParams {
                count,
                updated_image_tag,
            }
            .build(cluster),
        ));
        experiments.extend(Self::new_land_blocking_suite(cluster).experiments);
        Ok(Self { experiments })
    }

    pub fn new_by_name(cluster: &Cluster, name: &str) -> Result<Self> {
        match name {
            "perf" => Ok(Self::new_perf_suite(cluster)),
            "pre_release" => Ok(Self::new_pre_release(cluster)),
            "land_blocking" => Ok(Self::new_land_blocking_suite(cluster)),
            "land_blocking_compat" => Self::new_land_blocking_compat_suite(cluster),
            other => Err(format_err!("Unknown suite: {}", other)),
        }
    }
}
<|endoftext|>


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

use crate::aptos_cli::setup_cli_test;
use aptos::{account::create::DEFAULT_FUNDED_COINS, test::CliTestFramework};
use aptos_config::{config::ApiConfig, utils::get_available_port};
use aptos_crypto::HashValue;
use aptos_rosetta::common::Y2K_SECS;
use aptos_rosetta::types::{
    AccountBalanceResponse, Block, BlockIdentifier, NetworkIdentifier, NetworkRequest,
    PartialBlockIdentifier,
};
use aptos_rosetta::{
    client::RosettaClient,
    common::native_coin,
    types::{AccountBalanceRequest, BlockRequest},
};
use aptos_types::account_address::AccountAddress;
use aptos_types::chain_id::ChainId;
use forge::{LocalSwarm, Node};
use std::{future::Future, time::Duration};
use tokio::task::JoinHandle;

pub async fn setup_test(
    num_nodes: usize,
    num_accounts: usize,
) -> (LocalSwarm, CliTestFramework, JoinHandle<()>, RosettaClient) {
    let (swarm, cli, faucet) = setup_cli_test(num_nodes).await;
    let validator = swarm.validators().next().unwrap();

    // And the client
    let rosetta_port = get_available_port();
    let rosetta_socket_addr = format!("127.0.0.1:{}", rosetta_port);
    let rosetta_url = format!("http://{}", rosetta_socket_addr.clone())
        .parse()
        .unwrap();
    let rosetta_client = RosettaClient::new(rosetta_url);
    let api_config = ApiConfig {
        enabled: true,
        address: rosetta_socket_addr.parse().unwrap(),
        tls_cert_path: None,
        tls_key_path: None,
        content_length_limit: None,
    };

    // Start the server
    let _rosetta = aptos_rosetta::bootstrap_async(
        swarm.chain_id(),
        api_config,
        Some(aptos_rest_client::Client::new(
            validator.rest_api_endpoint(),
        )),
    )
    .await
    .unwrap();

    // Create accounts
    for i in 0..num_accounts {
        cli.create_account_with_faucet(i).await.unwrap();
    }
    (swarm, cli, faucet, rosetta_client)
}

#[tokio::test]
async fn test_account_balance() {
    let (swarm, cli, _faucet, rosetta_client) = setup_test(1, 1).await;

    cli.create_account_with_faucet(0).await.unwrap();
    let account = CliTestFramework::account_id(0);
    let chain_id = swarm.chain_id();

    // At time 0, there should be 0 balance
    let response = get_balance(&rosetta_client, chain_id, account, 0)
        .await
        .unwrap();
    assert_eq!(
        response.block_identifier,
        BlockIdentifier {
            index: 0,
            hash: HashValue::zero().to_hex(),
        }
    );

    // At some time before version 100, the account should exist
    let mut successful_version = None;
    for i in 1..100 {
        let response = get_balance(&rosetta_client, chain_id, account, i)
            .await
            .unwrap();
        let amount = response.balances.first().unwrap();
        if amount.value == DEFAULT_FUNDED_COINS.to_string() {
            successful_version = Some(i);
            break;
        }
    }

    if successful_version.is_none() {
        panic!("Failed to find account balance increase")
    }

    // TODO: Send money
    // TODO: Fail request due to bad transaction
    // TODO: Receive money
    // TODO: Recieve money by faucet
}

async fn get_balance(
    rosetta_client: &RosettaClient,
    chain_id: ChainId,
    account: AccountAddress,
    index: u64,
) -> anyhow::Result<AccountBalanceResponse> {
    let request = AccountBalanceRequest {
        network_identifier: chain_id.into(),
        account_identifier: account.into(),
        block_identifier: Some(PartialBlockIdentifier {
            index: Some(index),
            hash: None,
        }),
        currencies: Some(vec![native_coin()]),
    };
    try_until_ok(|| rosetta_client.account_balance(&request)).await
}

#[tokio::test]
async fn test_block() {
    let (swarm, _cli, _faucet, rosetta_client) = setup_test(1, 0).await;
    let chain_id = swarm.chain_id();

    let request_genesis = BlockRequest::by_index(chain_id, 0);
    let by_version_response = try_until_ok(|| rosetta_client.block(&request_genesis))
        .await
        .unwrap();
    let genesis_block = by_version_response.block.unwrap();

    // Genesis txn should always have parent be same as block
    assert_eq!(
        genesis_block.block_identifier,
        genesis_block.parent_block_identifier
    );
    assert_eq!(
        HashValue::zero().to_hex(),
        genesis_block.block_identifier.hash,
    );
    assert_eq!(0, genesis_block.block_identifier.index);

    // Genesis timestamp is always Y2K
    assert_eq!(Y2K_SECS, genesis_block.timestamp);

    // There should only be the genesis transaction
    assert_eq!(1, genesis_block.transactions.len());
    let genesis_txn = genesis_block.transactions.first().unwrap();

    // Version should match as 0
    assert_eq!(
        0,
        genesis_txn.metadata.unwrap().version.0,
        "Genesis version"
    );

    // There should be at least one transfer in genesis
    assert!(!genesis_txn.operations.is_empty());

    // Get genesis txn by hash
    let request_genesis_by_hash =
        BlockRequest::by_hash(chain_id, genesis_block.block_identifier.hash.clone());
    let by_hash_response = rosetta_client
        .block(&request_genesis_by_hash)
        .await
        .unwrap();
    let genesis_block_by_hash = by_hash_response.block.unwrap();

    // Both blocks should be the same
    assert_eq!(genesis_block, genesis_block_by_hash);

    // Responses should be idempotent
    let response = rosetta_client.block(&request_genesis).await.unwrap();
    assert_eq!(response.block.unwrap(), genesis_block_by_hash);
    let response = rosetta_client
        .block(&request_genesis_by_hash)
        .await
        .unwrap();
    assert_eq!(response.block.unwrap(), genesis_block_by_hash);

    // Block 1 is always a reconfig with exactly 1 txn
    let block_1 = get_block(&rosetta_client, chain_id, 1).await;
    assert_eq!(1, block_1.transactions.len());
    // Block metadata won't have operations
    assert!(block_1.transactions.first().unwrap().operations.is_empty());
    assert!(block_1.timestamp > genesis_block.timestamp);

    // Block 2 is always a standard block with 2 or more txns
    let block_2 = get_block(&rosetta_client, chain_id, 2).await;
    assert!(block_2.transactions.len() >= 2);
    // Block metadata won't have operations
    assert!(block_2.transactions.first().unwrap().operations.is_empty());
    // StateCheckpoint won't have operations
    assert!(block_2.transactions.last().unwrap().operations.is_empty());
    assert!(block_2.timestamp >= block_1.timestamp);

    // No input should give the latest version, not the genesis txn
    let request_latest = BlockRequest::latest(chain_id);
    let response = rosetta_client.block(&request_latest).await.unwrap();
    let latest_block = response.block.unwrap();

    // The latest block should always come after genesis
    assert!(latest_block.block_identifier.index >= block_2.block_identifier.index);
    assert!(latest_block.timestamp >= block_2.timestamp);

    // The parent should always be exactly one version before
    assert_eq!(
        latest_block.parent_block_identifier.index,
        latest_block.block_identifier.index - 1
    );

    // There should be at least 1 txn
    assert!(latest_block.transactions.len() > 1);

    // We should be able to query it again by hash or by version and it is the same
    let request_latest_by_version =
        BlockRequest::by_index(chain_id, latest_block.block_identifier.index);
    let latest_block_by_version = rosetta_client
        .block(&request_latest_by_version)
        .await
        .unwrap()
        .block
        .unwrap();
    let request_latest_by_hash =
        BlockRequest::by_hash(chain_id, latest_block.block_identifier.hash.clone());
    let latest_block_by_hash = rosetta_client
        .block(&request_latest_by_hash)
        .await
        .unwrap()
        .block
        .unwrap();

    assert_eq!(latest_block, latest_block_by_version);
    assert_eq!(latest_block_by_hash, latest_block_by_version);

    // Wait until we get a new block processed
    let network_request = NetworkRequest {
        network_identifier: NetworkIdentifier::from(chain_id),
    };
    while rosetta_client
        .network_status(&network_request)
        .await
        .unwrap()
        .current_block_identifier
        .index
        == latest_block.block_identifier.index
    {
        tokio::time::sleep(Duration::from_micros(10)).await
    }

    // And querying latest again should get yet another transaction in the future
    let newer_block = rosetta_client
        .block(&request_latest)
        .await
        .unwrap()
        .block
        .unwrap();
    assert!(newer_block.block_identifier.index >= latest_block.block_identifier.index);
    assert!(newer_block.timestamp >= latest_block.timestamp);
}

async fn get_block(rosetta_client: &RosettaClient, chain_id: ChainId, index: u64) -> Block {
    let rosetta_client = (*rosetta_client).clone();
    let request = BlockRequest::by_index(chain_id, index);
    try_until_ok(|| rosetta_client.block(&request))
        .await
        .unwrap()
        .block
        .unwrap()
}

/// Try for 2 seconds to get a response.  This handles the fact that it's starting async
async fn try_until_ok<F, Fut, T>(function: F) -> anyhow::Result<T>
where
    F: Fn() -> Fut,
    Fut: Future<Output = anyhow::Result<T>>,
{
    let mut result = Err(anyhow::Error::msg("Failed to get response"));
    for _ in 1..10 {
        result = function().await;
        if result.is_ok() {
            break;
        }
        tokio::time::sleep(Duration::from_millis(200)).await;
    }

    result
}
<commit_msg>[aptos-rosetta] Add E2E tests for network APIs<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::aptos_cli::setup_cli_test;
use aptos::{account::create::DEFAULT_FUNDED_COINS, test::CliTestFramework};
use aptos_config::{config::ApiConfig, utils::get_available_port};
use aptos_crypto::HashValue;
use aptos_rosetta::common::{BLOCKCHAIN, Y2K_SECS};
use aptos_rosetta::types::{
    AccountBalanceResponse, Block, BlockIdentifier, NetworkIdentifier, NetworkRequest,
    PartialBlockIdentifier,
};
use aptos_rosetta::{
    client::RosettaClient,
    common::native_coin,
    types::{AccountBalanceRequest, BlockRequest},
    ROSETTA_VERSION,
};
use aptos_types::account_address::AccountAddress;
use aptos_types::chain_id::ChainId;
use forge::{LocalSwarm, Node};
use std::{future::Future, time::Duration};
use tokio::task::JoinHandle;

pub async fn setup_test(
    num_nodes: usize,
    num_accounts: usize,
) -> (LocalSwarm, CliTestFramework, JoinHandle<()>, RosettaClient) {
    let (swarm, cli, faucet) = setup_cli_test(num_nodes).await;
    let validator = swarm.validators().next().unwrap();

    // And the client
    let rosetta_port = get_available_port();
    let rosetta_socket_addr = format!("127.0.0.1:{}", rosetta_port);
    let rosetta_url = format!("http://{}", rosetta_socket_addr.clone())
        .parse()
        .unwrap();
    let rosetta_client = RosettaClient::new(rosetta_url);
    let api_config = ApiConfig {
        enabled: true,
        address: rosetta_socket_addr.parse().unwrap(),
        tls_cert_path: None,
        tls_key_path: None,
        content_length_limit: None,
    };

    // Start the server
    let _rosetta = aptos_rosetta::bootstrap_async(
        swarm.chain_id(),
        api_config,
        Some(aptos_rest_client::Client::new(
            validator.rest_api_endpoint(),
        )),
    )
    .await
    .unwrap();

    // Create accounts
    for i in 0..num_accounts {
        cli.create_account_with_faucet(i).await.unwrap();
    }
    (swarm, cli, faucet, rosetta_client)
}

#[tokio::test]
async fn test_network() {
    let (swarm, _, _, rosetta_client) = setup_test(1, 1).await;
    let chain_id = swarm.chain_id();

    // We only support one network, this network
    let networks = rosetta_client.network_list().await.unwrap();
    assert_eq!(1, networks.network_identifiers.len());
    let network_id = networks.network_identifiers.first().unwrap();
    assert_eq!(BLOCKCHAIN, network_id.blockchain);
    assert_eq!(chain_id.to_string(), network_id.network);

    let request = NetworkRequest {
        network_identifier: NetworkIdentifier::from(chain_id),
    };
    let options = rosetta_client.network_options(&request).await.unwrap();
    assert_eq!(ROSETTA_VERSION, options.version.rosetta_version);

    // TODO: Check other options

    let request = NetworkRequest {
        network_identifier: NetworkIdentifier::from(chain_id),
    };
    let status = rosetta_client.network_status(&request).await.unwrap();
    assert!(status.current_block_identifier.index > 0);
    assert!(status.current_block_timestamp > Y2K_SECS);
    assert_eq!(
        BlockIdentifier {
            index: 0,
            hash: HashValue::zero().to_hex()
        },
        status.genesis_block_identifier
    );
    assert_eq!(
        Some(status.genesis_block_identifier),
        status.oldest_block_identifier,
    );
}

#[tokio::test]
async fn test_account_balance() {
    let (swarm, cli, _faucet, rosetta_client) = setup_test(1, 1).await;

    cli.create_account_with_faucet(0).await.unwrap();
    let account = CliTestFramework::account_id(0);
    let chain_id = swarm.chain_id();

    // At time 0, there should be 0 balance
    let response = get_balance(&rosetta_client, chain_id, account, 0)
        .await
        .unwrap();
    assert_eq!(
        response.block_identifier,
        BlockIdentifier {
            index: 0,
            hash: HashValue::zero().to_hex(),
        }
    );

    // At some time before version 100, the account should exist
    let mut successful_version = None;
    for i in 1..100 {
        let response = get_balance(&rosetta_client, chain_id, account, i)
            .await
            .unwrap();
        let amount = response.balances.first().unwrap();
        if amount.value == DEFAULT_FUNDED_COINS.to_string() {
            successful_version = Some(i);
            break;
        }
    }

    if successful_version.is_none() {
        panic!("Failed to find account balance increase")
    }

    // TODO: Send money
    // TODO: Fail request due to bad transaction
    // TODO: Receive money
    // TODO: Recieve money by faucet
}

async fn get_balance(
    rosetta_client: &RosettaClient,
    chain_id: ChainId,
    account: AccountAddress,
    index: u64,
) -> anyhow::Result<AccountBalanceResponse> {
    let request = AccountBalanceRequest {
        network_identifier: chain_id.into(),
        account_identifier: account.into(),
        block_identifier: Some(PartialBlockIdentifier {
            index: Some(index),
            hash: None,
        }),
        currencies: Some(vec![native_coin()]),
    };
    try_until_ok(|| rosetta_client.account_balance(&request)).await
}

#[tokio::test]
async fn test_block() {
    let (swarm, _cli, _faucet, rosetta_client) = setup_test(1, 0).await;
    let chain_id = swarm.chain_id();

    let request_genesis = BlockRequest::by_index(chain_id, 0);
    let by_version_response = try_until_ok(|| rosetta_client.block(&request_genesis))
        .await
        .unwrap();
    let genesis_block = by_version_response.block.unwrap();

    // Genesis txn should always have parent be same as block
    assert_eq!(
        genesis_block.block_identifier,
        genesis_block.parent_block_identifier
    );
    assert_eq!(
        HashValue::zero().to_hex(),
        genesis_block.block_identifier.hash,
    );
    assert_eq!(0, genesis_block.block_identifier.index);

    // Genesis timestamp is always Y2K
    assert_eq!(Y2K_SECS, genesis_block.timestamp);

    // There should only be the genesis transaction
    assert_eq!(1, genesis_block.transactions.len());
    let genesis_txn = genesis_block.transactions.first().unwrap();

    // Version should match as 0
    assert_eq!(
        0,
        genesis_txn.metadata.unwrap().version.0,
        "Genesis version"
    );

    // There should be at least one transfer in genesis
    assert!(!genesis_txn.operations.is_empty());

    // Get genesis txn by hash
    let request_genesis_by_hash =
        BlockRequest::by_hash(chain_id, genesis_block.block_identifier.hash.clone());
    let by_hash_response = rosetta_client
        .block(&request_genesis_by_hash)
        .await
        .unwrap();
    let genesis_block_by_hash = by_hash_response.block.unwrap();

    // Both blocks should be the same
    assert_eq!(genesis_block, genesis_block_by_hash);

    // Responses should be idempotent
    let response = rosetta_client.block(&request_genesis).await.unwrap();
    assert_eq!(response.block.unwrap(), genesis_block_by_hash);
    let response = rosetta_client
        .block(&request_genesis_by_hash)
        .await
        .unwrap();
    assert_eq!(response.block.unwrap(), genesis_block_by_hash);

    // Block 1 is always a reconfig with exactly 1 txn
    let block_1 = get_block(&rosetta_client, chain_id, 1).await;
    assert_eq!(1, block_1.transactions.len());
    // Block metadata won't have operations
    assert!(block_1.transactions.first().unwrap().operations.is_empty());
    assert!(block_1.timestamp > genesis_block.timestamp);

    // Block 2 is always a standard block with 2 or more txns
    let block_2 = get_block(&rosetta_client, chain_id, 2).await;
    assert!(block_2.transactions.len() >= 2);
    // Block metadata won't have operations
    assert!(block_2.transactions.first().unwrap().operations.is_empty());
    // StateCheckpoint won't have operations
    assert!(block_2.transactions.last().unwrap().operations.is_empty());
    assert!(block_2.timestamp >= block_1.timestamp);

    // No input should give the latest version, not the genesis txn
    let request_latest = BlockRequest::latest(chain_id);
    let response = rosetta_client.block(&request_latest).await.unwrap();
    let latest_block = response.block.unwrap();

    // The latest block should always come after genesis
    assert!(latest_block.block_identifier.index >= block_2.block_identifier.index);
    assert!(latest_block.timestamp >= block_2.timestamp);

    // The parent should always be exactly one version before
    assert_eq!(
        latest_block.parent_block_identifier.index,
        latest_block.block_identifier.index - 1
    );

    // There should be at least 1 txn
    assert!(latest_block.transactions.len() > 1);

    // We should be able to query it again by hash or by version and it is the same
    let request_latest_by_version =
        BlockRequest::by_index(chain_id, latest_block.block_identifier.index);
    let latest_block_by_version = rosetta_client
        .block(&request_latest_by_version)
        .await
        .unwrap()
        .block
        .unwrap();
    let request_latest_by_hash =
        BlockRequest::by_hash(chain_id, latest_block.block_identifier.hash.clone());
    let latest_block_by_hash = rosetta_client
        .block(&request_latest_by_hash)
        .await
        .unwrap()
        .block
        .unwrap();

    assert_eq!(latest_block, latest_block_by_version);
    assert_eq!(latest_block_by_hash, latest_block_by_version);

    // Wait until we get a new block processed
    let network_request = NetworkRequest {
        network_identifier: NetworkIdentifier::from(chain_id),
    };
    while rosetta_client
        .network_status(&network_request)
        .await
        .unwrap()
        .current_block_identifier
        .index
        == latest_block.block_identifier.index
    {
        tokio::time::sleep(Duration::from_micros(10)).await
    }

    // And querying latest again should get yet another transaction in the future
    let newer_block = rosetta_client
        .block(&request_latest)
        .await
        .unwrap()
        .block
        .unwrap();
    assert!(newer_block.block_identifier.index >= latest_block.block_identifier.index);
    assert!(newer_block.timestamp >= latest_block.timestamp);
}

async fn get_block(rosetta_client: &RosettaClient, chain_id: ChainId, index: u64) -> Block {
    let rosetta_client = (*rosetta_client).clone();
    let request = BlockRequest::by_index(chain_id, index);
    try_until_ok(|| rosetta_client.block(&request))
        .await
        .unwrap()
        .block
        .unwrap()
}

/// Try for 2 seconds to get a response.  This handles the fact that it's starting async
async fn try_until_ok<F, Fut, T>(function: F) -> anyhow::Result<T>
where
    F: Fn() -> Fut,
    Fut: Future<Output = anyhow::Result<T>>,
{
    let mut result = Err(anyhow::Error::msg("Failed to get response"));
    for _ in 1..10 {
        result = function().await;
        if result.is_ok() {
            break;
        }
        tokio::time::sleep(Duration::from_millis(200)).await;
    }

    result
}
<|endoftext|>


<commit_before>use ::opcodes::{AddressingMode, OpCode};

use cpu::cpu_error::CpuError;
use cpu::flags::StatusFlags;
use cpu::memory_bus::MemoryBus;
use cpu::registers::Registers;

const DEFAULT_CODE_SEGMENT_START_ADDRESS: u16 = 0xC000;  // Default to a 16KB ROM, leaving 32KB of main memory

pub enum Operand {
    Immediate(u8),
    Memory(u16),
    Implied,
}

/// A representation of a 6502 microprocessor
pub struct Cpu {
    pub memory: MemoryBus,
    pub registers: Registers,
    pub flags: StatusFlags,
}

pub type CpuLoadResult = Result<(), CpuError>;
pub type CpuStepResult = Result<(), CpuError>;

impl Cpu {
    /// Returns a default instance of a Cpu
    pub fn new() -> Cpu {
        Cpu {
            memory: MemoryBus::new(),
            registers: Registers::new(),
            flags: Default::default(),
        }
    }

    /// Loads code into the Cpu main memory at an optional offset. If no
    /// offset is provided, the Cpu will, by default, load the code into
    /// main memory at 0xC000
    pub fn load<T>(&mut self, code: &[u8], addr: T) -> CpuLoadResult
        where T: Into<Option<u16>>
    {
        let addr = addr.into();
        let addr: u16 = if addr.is_some() {
            let addr = addr.unwrap();
            if addr as u32 + code.len() as u32 > u16::max_value() as u32 {
                return Err(CpuError::code_segment_out_of_range(addr));
            } else {
                addr
            }
        } else {
            DEFAULT_CODE_SEGMENT_START_ADDRESS
        };

        for x in 0..code.len() {
            self.memory.write_byte(addr + x as u16, code[x]);
        }

        // Set the Program Counter to point at the
        // start address of the code segment
        self.registers.PC = addr;

        Ok(())
    }

    /// Runs N instructions of code through the Cpu
    pub fn step_n(&mut self, n: u32) -> CpuStepResult {
        for i in 0..n {
            self.step()?;
        }

        Ok(())
    }

    /// Runs a single instruction of code through the Cpu
    pub fn step(&mut self) -> CpuStepResult {
        let byte = self.memory.read_byte(self.registers.PC);

        if let Some(opcode) = OpCode::from_raw_byte(byte) {
            let operand = self.get_operand_from_opcode(&opcode);

            match opcode.mnemonic {
                "ADC" => self.adc(),
                "AND" => self.and(&operand),
                "CLD" => self.set_decimal_flag(false),
                "LDA" => self.lda(&operand),
                "SED" => self.set_decimal_flag(true),
                "STA" => self.sta(&operand),
                _ => return Err(CpuError::unknown_opcode(self.registers.PC, opcode.code)),
            }

            self.registers.PC += opcode.length as u16;

            Ok(())
        } else {
            Err(CpuError::unknown_opcode(self.registers.PC, byte))
        }
    }

    fn get_operand_from_opcode(&self, opcode: &OpCode) -> Operand {
        use ::opcodes::AddressingMode::*;

        let operand_start = self.registers.PC + 1;

        match opcode.mode {
            Unknown => unreachable!(),
            Implied => Operand::Implied,
            Immediate => Operand::Immediate(self.read_byte(operand_start)),
            Relative => Operand::Immediate(self.read_byte(operand_start)),
            Accumulator => Operand::Implied,
            ZeroPage => Operand::Memory((self.read_byte(operand_start) as u16) & 0xFF),
            ZeroPageX => {
                Operand::Memory((self.registers.X as u16 + self.read_byte(operand_start) as u16) &
                                0xFF)
            }
            ZeroPageY => {
                Operand::Memory((self.registers.Y as u16 + self.read_byte(operand_start) as u16) &
                                0xFF)
            }
            Absolute => Operand::Memory(self.read_u16(operand_start)),
            AbsoluteX => Operand::Memory(self.registers.X as u16 + self.read_u16(operand_start)),
            AbsoluteY => Operand::Memory(self.registers.Y as u16 + self.read_u16(operand_start)),
            Indirect => Operand::Memory(self.read_u16(self.read_u16(operand_start))),
            IndirectX => {
                Operand::Memory(self.read_u16((self.registers.X as u16 +
                                               self.read_byte(self.registers.PC + 1) as u16) &
                                              0xFF))
            }
            IndirectY => {
                Operand::Memory(self.registers.Y as u16 +
                                self.read_u16(self.read_byte(self.registers.PC + 1) as u16))
            }
        }
    }

    fn unwrap_immediate(&self, operand: &Operand) -> u8 {
        match *operand {
            Operand::Immediate(byte) => byte,
            Operand::Memory(addr) => self.read_byte(addr),
            Operand::Implied => 0,
        }
    }

    fn unwrap_address(&self, operand: &Operand) -> u16 {
        match *operand {
            Operand::Immediate(byte) => byte as u16,
            Operand::Memory(addr) => addr,
            Operand::Implied => 0,
        }
    }

    // ## OpCode handlers ##

    fn adc(&mut self) {
        // This is implemented on the information provided here:
        // http://www.electrical4u.com/bcd-or-binary-coded-decimal-bcd-conversion-addition-subtraction/
        // and here:
        // http://www.6502.org/tutorials/decimal_mode.html,
        // and here:
        // http://www.atariarchives.org/2bml/chapter_10.php,
        // and also here:
        // http://stackoverflow.com/questions/29193303/6502-emulation-proper-way-to-implement-adc-and-sbc

        let carry = if self.flags.carry { 1 } else { 0 };
        let value = self.read_byte(self.registers.PC + 1) as u16;

        // Do normal binary arithmetic first
        let mut result = self.registers.A as u16 + value as u16 + carry as u16;

        // Handle packed binary coded decimal
        if self.flags.decimal {
            if (self.registers.A as u16 & 0x0F) + (value & 0x0F) + carry > 0x09 {
                result += 0x06;
            }

            if result > 0x99 {
                result += 0x60;
            }

            self.flags.carry = (result & 0x100) == 0x100;
        } else {
            self.flags.carry = result > 0xFF;
        }

        self.flags.zero = result == 0;
        self.flags.sign = result > 127;
        self.flags.overflow = ((self.registers.A as u16 ^ result) & (value ^ result) & 0x80) ==
                              0x80;

        self.registers.A = result as u8 & 0xFF;
    }

    fn and(&mut self, operand: &Operand) {
        let value = self.unwrap_immediate(&operand);
        let result = self.registers.A & value;

        self.registers.A = result;

        self.flags.zero = result == 0;
    }

    fn lda(&mut self, operand: &Operand) {
        let value = self.unwrap_immediate(&operand);

        self.registers.A = value;
    }

    fn sta(&mut self, operand: &Operand) {
        let addr = self.unwrap_address(&operand);
        let value = self.registers.A;

        self.write_byte(addr, value);
    }

    fn set_decimal_flag(&mut self, value: bool) {
        self.flags.decimal = value;
    }

    /// Convenience wrapper for accessing a byte
    /// in memory
    fn read_byte(&self, addr: u16) -> u8 {
        self.memory.read_byte(addr)
    }

    /// Convenience wrapper for writing a byte
    /// to memory
    fn write_byte(&mut self, addr: u16, byte: u8) {
        self.memory.write_byte(addr, byte);
    }

    /// Convenience wrapper for accessing a word
    /// in memory
    fn read_u16(&self, addr: u16) -> u16 {
        self.memory.read_u16(addr)
    }
}

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

    #[test]
    fn can_instantiate_cpu() {
        let cpu = Cpu::new();

        assert!(0 == 0);
    }

    #[test]
    fn can_load_code_segment_into_memory() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);

        let memory_sum: u32 = cpu.memory.iter().map(|n| *n as u32).sum();
        assert_eq!(46, memory_sum);
    }

    #[test]
    fn can_load_code_segment_at_default_address() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);

        assert_eq!(0x0D, cpu.memory.read_byte(0xC003));
        assert_eq!(0x0C, cpu.memory.read_byte(0xC002));
        assert_eq!(0x0B, cpu.memory.read_byte(0xC001));
        assert_eq!(0x0A, cpu.memory.read_byte(0xC000));
    }

    #[test]
    fn can_load_code_segment_at_specific_address() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], 0xF000);

        assert_eq!(0x0D, cpu.memory.read_byte(0xF003));
        assert_eq!(0x0C, cpu.memory.read_byte(0xF002));
        assert_eq!(0x0B, cpu.memory.read_byte(0xF001));
        assert_eq!(0x0A, cpu.memory.read_byte(0xF000));
    }

    #[test]
    fn errors_when_code_segment_extends_past_memory_bounds() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        let load_result = cpu.load(&fake_code[..], 0xFFFD);

        assert_eq!(Err(CpuError::code_segment_out_of_range(0xFFFD)),
                   load_result);
    }

    #[test]
    fn errors_on_unknown_opcode() {
        let fake_code = vec![0xC3];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);
        let step_result: CpuStepResult = cpu.step();

        assert_eq!(Err(CpuError::unknown_opcode(0xC000, 0xC3)), step_result);// This is the unofficial DCP (d,X) opcode
    }

    #[test]
    fn can_get_operand_from_opcode() {
        let fake_code = vec![0xC3];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);
        let step_result: CpuStepResult = cpu.step();
    }

    #[test]
    fn adc_can_set_decimal_flag() {
        let code = vec![0xF8];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step();

        assert_eq!(true, cpu.flags.decimal);
    }

    #[test]
    fn adc_can_disable_decimal_flag() {
        let code = vec![0xD8];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step();

        assert_eq!(false, cpu.flags.decimal);
    }

    #[test]
    fn adc_can_add_basic_numbers() {
        let code = vec![0xA9, 0x05, 0x69, 0x03];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(8, cpu.registers.A);
    }

    #[test]
    fn adc_can_add_basic_numbers_set_carry_and_wrap_around() {
        let code = vec![0xA9, 0xFD, 0x69, 0x05];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(2, cpu.registers.A);
        assert_eq!(true, cpu.flags.carry);
    }

    #[test]
    fn adc_can_add_numbers_in_binary_coded_decimal() {
        let code = vec![0xF8, 0xA9, 0x05, 0x69, 0x05];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(3);

        assert_eq!(true, cpu.flags.decimal);
        assert_eq!(0x10, cpu.registers.A);
    }

    #[test]
    fn adc_can_add_numbers_in_binary_coded_decimal_and_set_carry() {
        let code = vec![0xF8, 0xA9, 0x95, 0x69, 0x10];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(3);

        assert_eq!(true, cpu.flags.decimal);
        assert_eq!(0x05, cpu.registers.A);
        assert_eq!(true, cpu.flags.carry);
    }

    #[test]
    fn sta_can_store_bytes_in_memory() {
        let code = vec![0xA9, 0x20, 0x8D, 0x00, 0x20];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(0x20, cpu.registers.A);
        assert_eq!(0x20, cpu.memory[0x2000]);
    }

    #[test]
    fn and_can_apply_logical_and_operation() {
        // Load 255 into A and mask it against 0x0F
        let code = vec![0xA9, 0xFF, 0x29, 0x0F];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(0x0F, cpu.registers.A);
    }
}
<commit_msg>Add test for sign flag set on logical AND<commit_after>use ::opcodes::{AddressingMode, OpCode};

use cpu::cpu_error::CpuError;
use cpu::flags::StatusFlags;
use cpu::memory_bus::MemoryBus;
use cpu::registers::Registers;

const DEFAULT_CODE_SEGMENT_START_ADDRESS: u16 = 0xC000;  // Default to a 16KB ROM, leaving 32KB of main memory

pub enum Operand {
    Immediate(u8),
    Memory(u16),
    Implied,
}

/// A representation of a 6502 microprocessor
pub struct Cpu {
    pub memory: MemoryBus,
    pub registers: Registers,
    pub flags: StatusFlags,
}

pub type CpuLoadResult = Result<(), CpuError>;
pub type CpuStepResult = Result<(), CpuError>;

impl Cpu {
    /// Returns a default instance of a Cpu
    pub fn new() -> Cpu {
        Cpu {
            memory: MemoryBus::new(),
            registers: Registers::new(),
            flags: Default::default(),
        }
    }

    /// Loads code into the Cpu main memory at an optional offset. If no
    /// offset is provided, the Cpu will, by default, load the code into
    /// main memory at 0xC000
    pub fn load<T>(&mut self, code: &[u8], addr: T) -> CpuLoadResult
        where T: Into<Option<u16>>
    {
        let addr = addr.into();
        let addr: u16 = if addr.is_some() {
            let addr = addr.unwrap();
            if addr as u32 + code.len() as u32 > u16::max_value() as u32 {
                return Err(CpuError::code_segment_out_of_range(addr));
            } else {
                addr
            }
        } else {
            DEFAULT_CODE_SEGMENT_START_ADDRESS
        };

        for x in 0..code.len() {
            self.memory.write_byte(addr + x as u16, code[x]);
        }

        // Set the Program Counter to point at the
        // start address of the code segment
        self.registers.PC = addr;

        Ok(())
    }

    /// Runs N instructions of code through the Cpu
    pub fn step_n(&mut self, n: u32) -> CpuStepResult {
        for i in 0..n {
            self.step()?;
        }

        Ok(())
    }

    /// Runs a single instruction of code through the Cpu
    pub fn step(&mut self) -> CpuStepResult {
        let byte = self.memory.read_byte(self.registers.PC);

        if let Some(opcode) = OpCode::from_raw_byte(byte) {
            let operand = self.get_operand_from_opcode(&opcode);

            match opcode.mnemonic {
                "ADC" => self.adc(),
                "AND" => self.and(&operand),
                "CLD" => self.set_decimal_flag(false),
                "LDA" => self.lda(&operand),
                "SED" => self.set_decimal_flag(true),
                "STA" => self.sta(&operand),
                _ => return Err(CpuError::unknown_opcode(self.registers.PC, opcode.code)),
            }

            self.registers.PC += opcode.length as u16;

            Ok(())
        } else {
            Err(CpuError::unknown_opcode(self.registers.PC, byte))
        }
    }

    fn get_operand_from_opcode(&self, opcode: &OpCode) -> Operand {
        use ::opcodes::AddressingMode::*;

        let operand_start = self.registers.PC + 1;

        match opcode.mode {
            Unknown => unreachable!(),
            Implied => Operand::Implied,
            Immediate => Operand::Immediate(self.read_byte(operand_start)),
            Relative => Operand::Immediate(self.read_byte(operand_start)),
            Accumulator => Operand::Implied,
            ZeroPage => Operand::Memory((self.read_byte(operand_start) as u16) & 0xFF),
            ZeroPageX => {
                Operand::Memory((self.registers.X as u16 + self.read_byte(operand_start) as u16) &
                                0xFF)
            }
            ZeroPageY => {
                Operand::Memory((self.registers.Y as u16 + self.read_byte(operand_start) as u16) &
                                0xFF)
            }
            Absolute => Operand::Memory(self.read_u16(operand_start)),
            AbsoluteX => Operand::Memory(self.registers.X as u16 + self.read_u16(operand_start)),
            AbsoluteY => Operand::Memory(self.registers.Y as u16 + self.read_u16(operand_start)),
            Indirect => Operand::Memory(self.read_u16(self.read_u16(operand_start))),
            IndirectX => {
                Operand::Memory(self.read_u16((self.registers.X as u16 +
                                               self.read_byte(self.registers.PC + 1) as u16) &
                                              0xFF))
            }
            IndirectY => {
                Operand::Memory(self.registers.Y as u16 +
                                self.read_u16(self.read_byte(self.registers.PC + 1) as u16))
            }
        }
    }

    fn unwrap_immediate(&self, operand: &Operand) -> u8 {
        match *operand {
            Operand::Immediate(byte) => byte,
            Operand::Memory(addr) => self.read_byte(addr),
            Operand::Implied => 0,
        }
    }

    fn unwrap_address(&self, operand: &Operand) -> u16 {
        match *operand {
            Operand::Immediate(byte) => byte as u16,
            Operand::Memory(addr) => addr,
            Operand::Implied => 0,
        }
    }

    // ## OpCode handlers ##

    fn adc(&mut self) {
        // This is implemented on the information provided here:
        // http://www.electrical4u.com/bcd-or-binary-coded-decimal-bcd-conversion-addition-subtraction/
        // and here:
        // http://www.6502.org/tutorials/decimal_mode.html,
        // and here:
        // http://www.atariarchives.org/2bml/chapter_10.php,
        // and also here:
        // http://stackoverflow.com/questions/29193303/6502-emulation-proper-way-to-implement-adc-and-sbc

        let carry = if self.flags.carry { 1 } else { 0 };
        let value = self.read_byte(self.registers.PC + 1) as u16;

        // Do normal binary arithmetic first
        let mut result = self.registers.A as u16 + value as u16 + carry as u16;

        // Handle packed binary coded decimal
        if self.flags.decimal {
            if (self.registers.A as u16 & 0x0F) + (value & 0x0F) + carry > 0x09 {
                result += 0x06;
            }

            if result > 0x99 {
                result += 0x60;
            }

            self.flags.carry = (result & 0x100) == 0x100;
        } else {
            self.flags.carry = result > 0xFF;
        }

        self.flags.zero = result == 0;
        self.flags.sign = result > 127;
        self.flags.overflow = ((self.registers.A as u16 ^ result) & (value ^ result) & 0x80) ==
                              0x80;

        self.registers.A = result as u8 & 0xFF;
    }

    fn and(&mut self, operand: &Operand) {
        let value = self.unwrap_immediate(&operand);
        let result = self.registers.A & value;

        self.registers.A = result;

        self.flags.zero = result == 0;
        self.flags.sign = result > 127;
    }

    fn lda(&mut self, operand: &Operand) {
        let value = self.unwrap_immediate(&operand);

        self.registers.A = value;
    }

    fn sta(&mut self, operand: &Operand) {
        let addr = self.unwrap_address(&operand);
        let value = self.registers.A;

        self.write_byte(addr, value);
    }

    fn set_decimal_flag(&mut self, value: bool) {
        self.flags.decimal = value;
    }

    /// Convenience wrapper for accessing a byte
    /// in memory
    fn read_byte(&self, addr: u16) -> u8 {
        self.memory.read_byte(addr)
    }

    /// Convenience wrapper for writing a byte
    /// to memory
    fn write_byte(&mut self, addr: u16, byte: u8) {
        self.memory.write_byte(addr, byte);
    }

    /// Convenience wrapper for accessing a word
    /// in memory
    fn read_u16(&self, addr: u16) -> u16 {
        self.memory.read_u16(addr)
    }
}

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

    #[test]
    fn can_instantiate_cpu() {
        let cpu = Cpu::new();

        assert!(0 == 0);
    }

    #[test]
    fn can_load_code_segment_into_memory() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);

        let memory_sum: u32 = cpu.memory.iter().map(|n| *n as u32).sum();
        assert_eq!(46, memory_sum);
    }

    #[test]
    fn can_load_code_segment_at_default_address() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);

        assert_eq!(0x0D, cpu.memory.read_byte(0xC003));
        assert_eq!(0x0C, cpu.memory.read_byte(0xC002));
        assert_eq!(0x0B, cpu.memory.read_byte(0xC001));
        assert_eq!(0x0A, cpu.memory.read_byte(0xC000));
    }

    #[test]
    fn can_load_code_segment_at_specific_address() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], 0xF000);

        assert_eq!(0x0D, cpu.memory.read_byte(0xF003));
        assert_eq!(0x0C, cpu.memory.read_byte(0xF002));
        assert_eq!(0x0B, cpu.memory.read_byte(0xF001));
        assert_eq!(0x0A, cpu.memory.read_byte(0xF000));
    }

    #[test]
    fn errors_when_code_segment_extends_past_memory_bounds() {
        let fake_code = vec![0x0A, 0x0B, 0x0C, 0x0D];
        let mut cpu = Cpu::new();
        let load_result = cpu.load(&fake_code[..], 0xFFFD);

        assert_eq!(Err(CpuError::code_segment_out_of_range(0xFFFD)),
                   load_result);
    }

    #[test]
    fn errors_on_unknown_opcode() {
        let fake_code = vec![0xC3];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);
        let step_result: CpuStepResult = cpu.step();

        assert_eq!(Err(CpuError::unknown_opcode(0xC000, 0xC3)), step_result);// This is the unofficial DCP (d,X) opcode
    }

    #[test]
    fn can_get_operand_from_opcode() {
        let fake_code = vec![0xC3];
        let mut cpu = Cpu::new();
        cpu.load(&fake_code[..], None);
        let step_result: CpuStepResult = cpu.step();
    }

    #[test]
    fn adc_can_set_decimal_flag() {
        let code = vec![0xF8];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step();

        assert_eq!(true, cpu.flags.decimal);
    }

    #[test]
    fn adc_can_disable_decimal_flag() {
        let code = vec![0xD8];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step();

        assert_eq!(false, cpu.flags.decimal);
    }

    #[test]
    fn adc_can_add_basic_numbers() {
        let code = vec![0xA9, 0x05, 0x69, 0x03];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(8, cpu.registers.A);
    }

    #[test]
    fn adc_can_add_basic_numbers_set_carry_and_wrap_around() {
        let code = vec![0xA9, 0xFD, 0x69, 0x05];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(2, cpu.registers.A);
        assert_eq!(true, cpu.flags.carry);
    }

    #[test]
    fn adc_can_add_numbers_in_binary_coded_decimal() {
        let code = vec![0xF8, 0xA9, 0x05, 0x69, 0x05];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(3);

        assert_eq!(true, cpu.flags.decimal);
        assert_eq!(0x10, cpu.registers.A);
    }

    #[test]
    fn adc_can_add_numbers_in_binary_coded_decimal_and_set_carry() {
        let code = vec![0xF8, 0xA9, 0x95, 0x69, 0x10];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(3);

        assert_eq!(true, cpu.flags.decimal);
        assert_eq!(0x05, cpu.registers.A);
        assert_eq!(true, cpu.flags.carry);
    }

    #[test]
    fn sta_can_store_bytes_in_memory() {
        let code = vec![0xA9, 0x20, 0x8D, 0x00, 0x20];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(0x20, cpu.registers.A);
        assert_eq!(0x20, cpu.memory[0x2000]);
    }

    #[test]
    fn and_can_apply_logical_and_operation() {
        // Load 255 into A and mask it against 0x0F
        let code = vec![0xA9, 0xFF, 0x29, 0x0F];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(0x0F, cpu.registers.A);
        assert_eq!(false, cpu.flags.sign);
    }

    #[test]
    fn and_can_apply_logical_and_operation_and_set_sign_flag() {
        // Load 255 into A and mask it against 0xF0
        let code = vec![0xA9, 0xFF, 0x29, 0xF0];
        let mut cpu = Cpu::new();
        cpu.load(&code[..], None);

        cpu.step_n(2);

        assert_eq!(0xF0, cpu.registers.A);
        assert_eq!(true, cpu.flags.sign);
    }
}
<|endoftext|>