Skip to content
Snippets Groups Projects
Select Git revision
  • ef9d58bd7c6a041f077d3500f92bb433de41ebbd
  • master default protected
2 results

controller.test.js

Blame
  • Forked from SOFT Core / SOFT 260 / Boost Board Game
    Source project has a limited visibility.
    controller.test.js 13.88 KiB
    /* eslint-disable no-magic-numbers */
    
    import { jest, describe, test, expect } from '@jest/globals';
    
    import { callsTo, anyUnexpectedCalls } from '../testing/awaitCalls.js';
    
    import Controller from './controller.js';
    
    function controllerWithMocks(engineURL, engineThreadURL, gameIdentifier) {
      globalThis.Worker = jest.fn().mockName('Worker').mockReturnValue({
        addEventListener: jest.fn().mockName('addEventListener'),
        postMessage: jest.fn().mockName('postMessage'),
      });
      const result = new Controller(
        engineURL,
        engineThreadURL,
        gameIdentifier,
        jest.fn().mockName('propertyHandler'),
        jest.fn().mockName('moveHandler'),
      );
      return result;
    }
    
    describe('the controller\'s automatic behaviors', () => {
      test('connect as needed when setting strength', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.setStrength(999);
        controller.setStrength(9999);
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
        ]);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['setoption strength 999'],
          ['isready'],
        ]);
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['setoption strength 999'],
          ['isready'],
          ['setoption strength 9999'],
          ['isready'],
        ]);
      });
      test('connect and start a game as needed when setting a line', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.setLine({ serialization: 'jkl' }, [{ serialization: 'mno' }, { serialization: 'pqr' }]);
        controller.setLine({ serialization: 'stu' }, []);
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
        ]);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
        ]);
        controller.receiveMessage('known');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
          ['setline jkl mno pqr'],
          ['isready'],
        ]);
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
          ['setline jkl mno pqr'],
          ['isready'],
          ['setline stu'],
          ['isready'],
        ]);
      });
      test('connect and start a game as needed when starting a search', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.go();
        controller.stop();
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
        ]);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
        ]);
        controller.receiveMessage('known');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
          ['go'],
          ['isready'],
        ]);
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
          ['go'],
          ['isready'],
          ['stop'],
          ['isready'],
        ]);
      });
    });
    
    describe('the controller\'s communication checks', () => {
      test('block communication when the engine protocol is too new', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.setLine({ serialization: 'jkl' }, []);
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
        ]);
        controller.receiveMessage('protocol 9999.9.9');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await anyUnexpectedCalls();
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
        ]);
      });
      test('block a game line if the engine does not know the game', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.setLine({ serialization: 'jkl' }, []);
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
        ]);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
        ]);
        controller.receiveMessage('unknown');
        controller.receiveMessage('readyok');
        await anyUnexpectedCalls();
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
        ]);
      });
      test('block starting an already started search', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.go();
        controller.go();
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
        ]);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
        ]);
        controller.receiveMessage('known');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
          ['go'],
          ['isready'],
        ]);
        controller.receiveMessage('readyok');
        await anyUnexpectedCalls();
        expect(controller.worker.postMessage.mock.calls).toEqual([
          ['bei def'],
          ['isready'],
          ['newgame ghi'],
          ['isready'],
          ['go'],
          ['isready'],
        ]);
      });
      test('block stopping an already stopped search', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.stop();
        await anyUnexpectedCalls();
        expect(controller.worker.postMessage.mock.calls).toEqual([]);
      });
    });
    
    describe('the controller\'s callbacks', () => {
      test('report engine properties', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.setStrength(999);
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('id name jkl');
        controller.receiveMessage('id author mno');
        controller.receiveMessage('id version pqr');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        expect(controller.propertyHandler.mock.calls).toEqual([
          ['name', 'jkl'],
          ['author', 'mno'],
          ['version', 'pqr'],
        ]);
      });
      test('report single moves', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('known');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.receiveMessage('move jkl');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
        ]);
      });
      test('report consecutive moves', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('known');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.receiveMessage('move jkl');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
        ]);
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.receiveMessage('move mno');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
          ['mno'],
        ]);
      });
      test('do not report unwanted moves from stopped searches', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('known');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.stop();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.receiveMessage('move jkl');
        expect(controller.moveHandler.mock.calls).toEqual([]);
        controller.stop();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.receiveMessage('move mno');
        expect(controller.moveHandler.mock.calls).toEqual([]);
        controller.receiveMessage('move pqr');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['pqr'],
        ]);
      });
      test('do report wanted moves from stopped searches', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('known');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.stop(true);
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.receiveMessage('move jkl');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
        ]);
        controller.stop(true);
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.receiveMessage('move mno');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
          ['mno'],
        ]);
        controller.receiveMessage('move pqr');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
          ['mno'],
          ['pqr'],
        ]);
      });
      test('do report late-arriving wanted moves from stopped searches', async() => {
        const controller = controllerWithMocks('abc', 'def', 'ghi');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('protocol 1.0.0');
        controller.receiveMessage('beiok');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('known');
        controller.receiveMessage('readyok');
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.stop(true);
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.stop(false);
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.go();
        await callsTo(controller.worker.postMessage);
        controller.receiveMessage('readyok');
        controller.receiveMessage('move jkl');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
        ]);
        controller.receiveMessage('move mno');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
        ]);
        controller.receiveMessage('move pqr');
        expect(controller.moveHandler.mock.calls).toEqual([
          ['jkl'],
          ['pqr'],
        ]);
      });
    });