use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
use turing_machine_rs::instruction::{Move, State};
use turing_machine_rs::machines::{Classic, Debugger};
use turing_machine_rs::program::{Extend, Program};
use turing_machine_rs::state::{Configuration, Tape};
use turing_machine_rs::TuringMachine;
#[cfg(test)]
mod copy {
use super::*;
fn new_custom_machine() -> Classic<char> {
let mut program = Program::new(vec![' '], State(1));
program.extend([(1, ' ', 1, ' ', Move::Right)]).unwrap();
Classic::new(program, ' ').unwrap()
}
#[test]
fn success_creation() {
let machine = new_custom_machine();
let _ = Debugger::new(machine);
}
#[test]
fn set_handlers() {
let machine = new_custom_machine();
let mut debugger = Debugger::new(machine);
let conf = Configuration::new_nrm(Tape::from(" ")).unwrap();
let buffer = Rc::new(RefCell::new(String::new()));
let c_buffer = buffer.clone();
debugger.set_c_handler(move |_| {
let mut buffer = c_buffer.borrow_mut();
buffer.push('c');
});
let conf = debugger.execute_once(conf).unwrap();
let i_buffer = buffer.clone();
debugger.set_i_handler(move |_, _| {
let mut buffer = i_buffer.borrow_mut();
buffer.push('i');
});
debugger.execute_once(conf).unwrap();
assert_eq!(String::from("cci"), buffer.deref().borrow().as_ref());
}
}
#[cfg(test)]
mod clone {
use super::*;
fn new_custom_machine() -> Classic<Box<char>> {
let mut program = Program::new(vec![Box::new(' ')], State(1));
program
.extend([(1, Box::new(' '), 1, Box::new(' '), Move::Right)])
.unwrap();
Classic::new(program, Box::new(' ')).unwrap()
}
#[test]
fn creation() {
let machine = new_custom_machine();
let _ = Debugger::new(machine);
}
#[test]
fn set_handlers() {
let machine = new_custom_machine();
let mut debugger = Debugger::new(machine);
let conf = Configuration::new_nrm(Tape::new(" ".chars().map(|ch| Box::new(ch)))).unwrap();
let buffer = Rc::new(RefCell::new(String::new()));
let c_buffer = buffer.clone();
debugger.set_c_handler(move |_| {
let mut buffer = c_buffer.borrow_mut();
buffer.push('c');
});
let conf = debugger.execute_once(conf).unwrap();
let i_buffer = buffer.clone();
debugger.set_i_handler(move |_, _| {
let mut buffer = i_buffer.borrow_mut();
buffer.push('i');
});
debugger.execute_once(conf).unwrap();
assert_eq!(String::from("cci"), buffer.deref().borrow().as_ref());
}
}
#[cfg(test)]
mod copy_turing_machine {
use super::*;
fn new_zerofy_machine() -> Classic<char> {
let mut program = Program::new(vec!['0', '1'], State(4));
program
.extend([
(1, '0', 2, '0', Move::Right),
(2, '0', 3, '0', Move::Left),
(2, '1', 2, '1', Move::Right),
(3, '0', 0, '0', Move::None),
(3, '1', 4, '0', Move::None),
(4, '0', 3, '0', Move::Left),
])
.unwrap();
Classic::new(program, '0').unwrap()
}
#[test]
fn execute() {
let machine = new_zerofy_machine();
let debugger = Debugger::new(machine);
let conf = Configuration::new_nrm(Tape::from("0110")).unwrap();
let result = debugger.execute(conf).unwrap();
let mut expected = Configuration::new_nrm(Tape::from("0000")).unwrap();
expected.state = State(0);
assert_eq!(expected, result);
}
#[test]
fn execute_once() {
let machine = new_zerofy_machine();
let debugger = Debugger::new(machine);
let conf = Configuration::new_nrm(Tape::from("0110")).unwrap();
let result = debugger
.execute_once(debugger.execute_once(conf).unwrap())
.unwrap();
let expected = Configuration::new(Tape::from("0110"), 2, State(2)).unwrap();
assert_eq!(expected, result);
}
#[test]
fn execute_until() {
let machine = new_zerofy_machine();
let debugger = Debugger::new(machine);
let conf = Configuration::new_nrm(Tape::from("0110")).unwrap();
let result = debugger
.execute_until(conf, |conf| conf.state == State(3))
.unwrap();
assert_eq!(
Configuration::new(Tape::from("0110"), 2, State(3)).unwrap(),
result
);
}
#[test]
fn translate_std() {
let mut program = Program::new(vec!['0', '1'], State(3));
program
.extend([
(1, '0', 2, '0', Move::Right),
(1, '1', 1, '1', Move::Left),
(2, '0', 3, '1', Move::Left),
(2, '1', 2, '1', Move::Right),
(3, '0', 0, '0', Move::None),
(3, '1', 3, '0', Move::Left),
])
.unwrap();
let machine = Classic::new(program, '0').unwrap();
let debugger = Debugger::new(machine);
let result = debugger.translate_std(Tape::from("010")).unwrap();
assert_eq!(result, Tape::from("0101"));
}
#[test]
fn translate_nrm() {
let mut program = Program::new(vec!['0', '1'], State(3));
program
.extend([
(1, '0', 2, '0', Move::Right),
(1, '1', 1, '1', Move::Left),
(2, '0', 3, '1', Move::Left),
(2, '1', 2, '1', Move::Right),
(3, '0', 0, '0', Move::None),
(3, '1', 3, '0', Move::Left),
])
.unwrap();
let machine = Classic::new(program, '0').unwrap();
let debugger = Debugger::new(machine);
let result = debugger.translate_nrm(Tape::from("010")).unwrap();
let expected = Tape::from("001");
assert_eq!(expected, result);
}
}
#[cfg(test)]
mod clone_turing_machine {
use super::*;
fn new_zerofy_machine() -> Classic<Box<char>> {
let mut program = Program::new(vec![Box::new('0'), Box::new('1')], State(4));
program
.extend([
(1, Box::new('0'), 2, Box::new('0'), Move::Right),
(2, Box::new('0'), 3, Box::new('0'), Move::Left),
(2, Box::new('1'), 2, Box::new('1'), Move::Right),
(3, Box::new('0'), 0, Box::new('0'), Move::None),
(3, Box::new('1'), 4, Box::new('0'), Move::None),
(4, Box::new('0'), 3, Box::new('0'), Move::Left),
])
.unwrap();
Classic::new(program, Box::new('0')).unwrap()
}
#[test]
fn execute() {
let machine = new_zerofy_machine();
let debugger = Debugger::new(machine);
let conf =
Configuration::new_nrm(Tape::new("0110".chars().map(|ch| Box::new(ch)))).unwrap();
let result = debugger.execute(conf).unwrap();
let mut expected =
Configuration::new_nrm(Tape::new("0000".chars().map(|ch| Box::new(ch)))).unwrap();
expected.state = State(0);
assert_eq!(expected, result);
}
#[test]
fn execute_once() {
let machine = new_zerofy_machine();
let debugger = Debugger::new(machine);
let conf =
Configuration::new_nrm(Tape::new("0110".chars().map(|ch| Box::new(ch)))).unwrap();
let result = debugger
.execute_once(debugger.execute_once(conf).unwrap())
.unwrap();
let expected = Configuration::new(
Tape::new("0110".chars().map(|ch| Box::new(ch))),
2,
State(2),
)
.unwrap();
assert_eq!(expected, result);
}
#[test]
fn execute_until() {
let machine = new_zerofy_machine();
let debugger = Debugger::new(machine);
let conf =
Configuration::new_nrm(Tape::new("0110".chars().map(|ch| Box::new(ch)))).unwrap();
let result = debugger
.execute_until(conf, |conf| conf.state == State(3))
.unwrap();
assert_eq!(
Configuration::new(
Tape::new("0110".chars().map(|ch| Box::new(ch))),
2,
State(3)
)
.unwrap(),
result
);
}
#[test]
fn translate_std() {
let mut program = Program::new(vec![Box::new('0'), Box::new('1')], State(3));
program
.extend([
(1, Box::new('0'), 2, Box::new('0'), Move::Right),
(1, Box::new('1'), 1, Box::new('1'), Move::Left),
(2, Box::new('0'), 3, Box::new('1'), Move::Left),
(2, Box::new('1'), 2, Box::new('1'), Move::Right),
(3, Box::new('0'), 0, Box::new('0'), Move::None),
(3, Box::new('1'), 3, Box::new('0'), Move::Left),
])
.unwrap();
let machine = Classic::new(program, Box::new('0')).unwrap();
let debugger = Debugger::new(machine);
let expected = debugger
.translate_std(Tape::new("010".chars().map(|ch| Box::new(ch))))
.unwrap();
assert_eq!(expected, Tape::new("0101".chars().map(|ch| Box::new(ch))));
}
#[test]
fn translate_nrm() {
let mut program = Program::new(vec![Box::new('0'), Box::new('1')], State(3));
program
.extend([
(1, Box::new('0'), 2, Box::new('0'), Move::Right),
(1, Box::new('1'), 1, Box::new('1'), Move::Left),
(2, Box::new('0'), 3, Box::new('1'), Move::Left),
(2, Box::new('1'), 2, Box::new('1'), Move::Right),
(3, Box::new('0'), 0, Box::new('0'), Move::None),
(3, Box::new('1'), 3, Box::new('0'), Move::Left),
])
.unwrap();
let machine = Classic::new(program, Box::new('0')).unwrap();
let debugger = Debugger::new(machine);
let result = debugger
.translate_nrm(Tape::new("010".chars().map(|ch| Box::new(ch))))
.unwrap();
let expected = Tape::new("001".chars().map(|ch| Box::new(ch)));
assert_eq!(expected, result);
}
}