/test/brainfuckSpec.js
https://gitlab.com/bxt/brainfuck-debugger · JavaScript · 413 lines · 341 code · 72 blank · 0 comment · 6 complexity · 8e68546f42592316b18ecb1aafe7ed7d MD5 · raw file
- import { expect } from './helper'
- import { create, isComment, isDone, minify, restart, run, step } from '../src/brainfuck'
- describe('brainfuck', function () {
- describe('#create(input, instructions)', function () {
- const machine = create('test input', 'test instructions')
- it('sets machine\'s input to first param', function () {
- expect(machine.input).to.equal('test input')
- })
- it('creates a machine at input position 0', function () {
- expect(machine.inputPointer).to.equal(0)
- })
- it('creates a machine at instruction 0', function () {
- expect(machine.instructionPointer).to.equal(0)
- })
- it('sets machine\'s instructions to second param', function () {
- expect(machine.instructions).to.equal('test instructions')
- })
- it('creates a machine with just one zero memory cell', function () {
- expect(machine.memory).to.deep.equal([0])
- })
- it('creates a machine at memory 0', function () {
- expect(machine.memoryPointer).to.equal(0)
- })
- it('creates a machine with empty output', function () {
- expect(machine.output).to.equal('')
- })
- })
- describe('#isComment(instruction)', function () {
- ;[',', '.', '+', '-', '<', '>', '[', ']'].forEach((instruction) => {
- it(`returns false for "${instruction}"`, function () {
- expect(isComment(instruction)).to.be.false()
- })
- })
- ;['#', '?', 'a', 'A', '1', '9', '0', '❤️'].forEach((instruction) => {
- it(`returns true for "${instruction}"`, function () {
- expect(isComment(instruction)).to.be.true()
- })
- })
- })
- describe('#isDone(machine)', function () {
- it(`returns false for a freshly created machine`, function () {
- const machine = create('', '.--')
- expect(isDone(machine)).to.be.false()
- })
- it(`returns true for a machine after run`, function () {
- const machine = create('', '.--')
- run(machine)
- expect(isDone(machine)).to.be.true()
- })
- it(`returns true for a machine without instructions`, function () {
- const machine = create('', '')
- expect(isDone(machine)).to.be.true()
- })
- })
- describe('#minify(instructions)', function () {
- it(`does nothing for a straightforwad program`, function () {
- expect(minify(',-.+')).to.equal(',-.+')
- })
- it(`removes all the comments`, function () {
- expect(minify(',a-b.c+d')).to.equal(',-.+')
- })
- it(`optimizes some no-ops`, function () {
- expect(minify('... move back < and forth > or add + and subtract - even repeatedly <-<>+> ...')).to.equal('......')
- })
- })
- describe('#restart(machine)', function () {
- const machine = create('test input', '.+++,')
- run(machine)
- restart(machine)
- it('does not change machine\'s input', function () {
- expect(machine.input).to.equal('test input')
- })
- it('sets the machine input position to 0', function () {
- expect(machine.inputPointer).to.equal(0)
- })
- it('sets the machine instruction pointer to 0', function () {
- expect(machine.instructionPointer).to.equal(0)
- })
- it('does not change machine\'s instructions', function () {
- expect(machine.instructions).to.equal('.+++,')
- })
- it('resets the machine to just one zero memory cell', function () {
- expect(machine.memory).to.deep.equal([0])
- })
- it('resets the machine memory pointer to 0', function () {
- expect(machine.memoryPointer).to.equal(0)
- })
- it('restets the output to be empty', function () {
- expect(machine.output).to.equal('')
- })
- })
- describe('#run(machine)', function () {
- it('prints back an input character', function () {
- const machine = create('abc', ',.')
- const output = run(machine)
- expect(output).to.equal('a')
- })
- it('prints a few characters', function () {
- const machine = create('', new Array(66).join('+') + '.+.+.')
- const output = run(machine)
- expect(output).to.equal('ABC')
- })
- it('prints back input characters', function () {
- const machine = create('abc', ',+.,++.,-.')
- const output = run(machine)
- expect(output).to.equal('bdb')
- })
- it('moves around the memory', function () {
- const machine = create('abc', '<<<,+>,++>,-<<.>.>.')
- const output = run(machine)
- expect(output).to.equal('bdb')
- })
- it('can do loops', function () {
- const machine = create('', '++++[>++++[>++++<-]<-]>+++++[>+.<-]')
- const output = run(machine)
- expect(output).to.equal('ABCDE')
- })
- it('reverses the input', function () {
- const machine = create('rewers', '+[>,]<[<]>->[>]<[.<]')
- const output = run(machine)
- expect(output).to.equal('srewer')
- })
- it('reverses the input (2)', function () {
- const machine = create('rewers', '+[>,]<<[>.<<]')
- const output = run(machine)
- expect(output).to.equal('srewer')
- })
- })
- describe('#step(machine)', function () {
- context('instruction is "."', function () {
- const machine = create('', '.--')
- machine.memory = [65]
- machine.output = 't'
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('appends the current memory to the output', function () {
- expect(machine.output).to.deep.equal('tA')
- })
- })
- context('instruction is ","', function () {
- const machine = create('A', ',..')
- step(machine)
- it('advances the input pointer', function () {
- expect(machine.inputPointer).to.equal(1)
- })
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('puts input in the memory', function () {
- expect(machine.memory).to.deep.equal([65])
- })
- })
- context('instruction is "+"', function () {
- context('machine is freshly created', function () {
- const machine = create('A', '+..')
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('increases the memory pointed to by 1', function () {
- expect(machine.memory).to.deep.equal([1])
- })
- })
- context('machine already has values', function () {
- const machine = create('A', '..+')
- machine.memory = [4, 5, 6]
- machine.memoryPointer = 1
- machine.instructionPointer = 2
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(3)
- })
- it('increases the memory pointed to by 1', function () {
- expect(machine.memory).to.deep.equal([4, 6, 6])
- })
- })
- })
- context('instruction is "-"', function () {
- context('machine is freshly created', function () {
- const machine = create('A', '-..')
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('decreases the memory pointed to by 1', function () {
- expect(machine.memory).to.deep.equal([-1])
- })
- })
- context('machine already has values', function () {
- const machine = create('A', '..-')
- machine.memory = [4, 5, 6]
- machine.memoryPointer = 1
- machine.instructionPointer = 2
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(3)
- })
- it('decreases the memory pointed to by 1', function () {
- expect(machine.memory).to.deep.equal([4, 4, 6])
- })
- })
- })
- context('instruction is ">"', function () {
- context('machine is freshly created', function () {
- const machine = create('A', '>..')
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('advances the memory pointer', function () {
- expect(machine.memoryPointer).to.equal(1)
- })
- it('adds a zero cell to the memory', function () {
- expect(machine.memory).to.deep.equal([0, 0])
- })
- })
- context('machine already has values', function () {
- const machine = create('A', '>..')
- machine.memory = [4, 5, 6]
- machine.memoryPointer = 1
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('advances the memory pointer', function () {
- expect(machine.memoryPointer).to.equal(2)
- })
- it('does not change the memory', function () {
- expect(machine.memory).to.deep.equal([4, 5, 6])
- })
- })
- })
- context('instruction is "<"', function () {
- context('machine is freshly created', function () {
- const machine = create('A', '<..')
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('does not change the memory pointer', function () {
- expect(machine.memoryPointer).to.equal(0)
- })
- it('adds a zero cell in front of the memory', function () {
- expect(machine.memory).to.deep.equal([0, 0])
- })
- })
- context('machine already has values', function () {
- context('memoryPointer is 0', function () {
- const machine = create('A', '<..')
- machine.memory = [4, 5, 6]
- machine.memoryPointer = 0
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('does not change the memory pointer', function () {
- expect(machine.memoryPointer).to.equal(0)
- })
- it('adds a zero cell in front of the memory', function () {
- expect(machine.memory).to.deep.equal([0, 4, 5, 6])
- })
- })
- context('memoryPointer is 1', function () {
- const machine = create('A', '<..')
- machine.memory = [4, 5, 6]
- machine.memoryPointer = 1
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(1)
- })
- it('sets the memory pointer back to 0', function () {
- expect(machine.memoryPointer).to.equal(0)
- })
- it('does not change the memory', function () {
- expect(machine.memory).to.deep.equal([4, 5, 6])
- })
- })
- })
- })
- context('instruction is "["', function () {
- context('machine is freshly created', function () {
- const machine = create('A', '[-[.]-]...')
- step(machine)
- it('advances the instruction pointer to after the matching ]', function () {
- expect(machine.instructionPointer).to.equal(7)
- })
- })
- context('machine already has values', function () {
- const machine = create('A', '..[-[.]-]...')
- machine.memory = [1]
- machine.instructionPointer = 2
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(3)
- })
- })
- })
- context('instruction is "]"', function () {
- context('the current cell is 0', function () {
- const machine = create('A', '..[-[.]-]...')
- machine.memory = [0]
- machine.instructionPointer = 8
- step(machine)
- it('advances the instruction pointer', function () {
- expect(machine.instructionPointer).to.equal(9)
- })
- })
- context('the current cell is 1', function () {
- const machine = create('A', '..[-[.]-]...')
- machine.memory = [1]
- machine.instructionPointer = 8
- step(machine)
- it('resets the instruction pointer to after the matching [', function () {
- expect(machine.instructionPointer).to.equal(3)
- })
- })
- })
- context('at a comment', function () {
- const machine = create('A', 'ccc+..')
- step(machine)
- it('advances the instruction pointer through the whole comment', function () {
- expect(machine.instructionPointer).to.equal(4)
- })
- it('runs the command after the comment', function () {
- expect(machine.memory).to.deep.equal([1])
- })
- })
- context('with comment after command', function () {
- const machine = create('A', 'ccc+cc..')
- step(machine)
- it('advances the instruction pointer through the comment afterwards', function () {
- expect(machine.instructionPointer).to.equal(6)
- })
- it('runs the command between the comments', function () {
- expect(machine.memory).to.deep.equal([1])
- })
- })
- })
- })