<commit_before>'use strict';
var _ = require('lodash'),
    BufferList = require('bl'),
    Promise = require('bluebird'),
    net = require('net'),
    expect = require('chai').expect,
    debug = require('debug')('amqp10:mock:server'),
    frames = require('../../../lib/frames'),
    tu = require('../../testing_utils');

function MockServer(options) {
  this._server = null;
  this._client = null;
  this._responses = [];
  this._expectedFrames = [];
  this._seenFrames = [];

  _.defaults(this, options, {
    hostname: '127.0.0.1',
    port: 4321,
    serverGoesFirst: false
  });
}

MockServer.prototype.address = function(user, pass) {
  if (!this.server) throw new Error('no server');

  var address = 'amqp://';
  if (!!user) address += user;
  if (!!pass) address += ':' + pass;
  if (!!user || !!pass) address += '@';
  address += this.server.address().address + ':' + this.server.address().port;
  return address;
};

MockServer.prototype.closeConnection = function() {
  if (this._client) {
    this._client.end();
  }
};

MockServer.prototype.setup = function() {
  var self = this;
  return new Promise(function(resolve, reject) {
    self.server = net.createServer(function(c) {
      debug('connection established');
      self._client = c;

      if (self.serverGoesFirst) {
        self._sendNextResponse();
      }

      c.on('end', function() {
        debug('connection terminated');
        self._client = undefined;
      });

      c.on('data', function(d) {
        debug('read: ', d.toString('hex'));
        self._checkExpectations(d);
      });
    });

    self.server.on('error', function(err) {
      reject(err);
    });

    self.server.listen(self.port, self.hostname, function() {
      debug('server listening on ' + self.port);
      resolve();
    });
  });
};

MockServer.prototype._checkExpectations = function(data) {
  var idx = 0, expectedFrame;
  while (this._expectedFrames.length) {
    expectedFrame = this._expectedFrames.shift();
    if (data.length < idx + expectedFrame.length) {
      this._expectedFrames.unshift(expectedFrame);
      break;
    }

    if (expectedFrame === false || expectedFrame === undefined) break;
    var actualFrame = data.slice(idx, idx + expectedFrame.length);
    debug('expected(', expectedFrame.length, '):', expectedFrame.toString('hex'));
    debug('  actual(', actualFrame.length, '):', actualFrame.toString('hex'));
    expect(actualFrame).to.eql(expectedFrame);
    if (this._expectedFrames[0] === false) break;
    if (idx >= data.length) break;
    idx += expectedFrame.length;
  }

  this._seenFrames.push(new BufferList(data));
  this._sendNextResponse();
};

MockServer.prototype.teardown = function() {
  var self = this;<commit_msg>refactor(mock-server): ensure expectations checked on full frames<commit_after>'use strict';
var _ = require('lodash'),
    BufferList = require('bl'),
    Promise = require('bluebird'),
    net = require('net'),
    expect = require('chai').expect,
    debug = require('debug')('amqp10:mock:server'),
    frames = require('../../../lib/frames'),
    tu = require('../../testing_utils'),
    constants = require('../../../lib/constants');

function MockServer(options) {
  this._server = null;
  this._client = null;
  this._responses = [];
  this._expectedFrames = [];
  this._seenFrames = [];

  _.defaults(this, options, {
    hostname: '127.0.0.1',
    port: 4321,
    serverGoesFirst: false
  });
}

MockServer.prototype.address = function(user, pass) {
  if (!this.server) throw new Error('no server');

  var address = 'amqp://';
  if (!!user) address += user;
  if (!!pass) address += ':' + pass;
  if (!!user || !!pass) address += '@';
  address += this.server.address().address + ':' + this.server.address().port;
  return address;
};

MockServer.prototype.closeConnection = function() {
  if (this._client) {
    this._client.end();
  }
};

MockServer.prototype.setup = function() {
  var self = this;
  return new Promise(function(resolve, reject) {
    self.server = net.createServer(function(c) {
      debug('connection established');
      self._client = c;
      self._buffer = new BufferList();

      if (self.serverGoesFirst) {
        self._sendNextResponse();
      }

      c.on('end', function() {
        debug('connection terminated');
        self._client = undefined;
      });

      c.on('data', function(d) {
        debug('read: ', d.toString('hex'));

        // special case for initial headers
        if (d.compare(constants.amqpVersion) === 0 ||
            d.compare(constants.saslVersion) === 0) {
          self._checkExpectations(d);
          return;
        }

        self._buffer.append(d);
        var checkBuffer = self._buffer.duplicate();
        let frame = frames.readFrame(checkBuffer, { verbose: false });
        if (!frame) return;

        var dataSize = self._buffer.length - checkBuffer.length;
        var data = self._buffer.slice(0, dataSize);
        self._buffer.consume(dataSize);
        self._checkExpectations(data);
      });
    });

    self.server.on('error', function(err) {
      reject(err);
    });

    self.server.listen(self.port, self.hostname, function() {
      debug('server listening on ' + self.port);
      resolve();
    });
  });
};

MockServer.prototype._checkExpectations = function(data) {
  var idx = 0, expectedFrame;
  while (this._expectedFrames.length) {
    expectedFrame = this._expectedFrames.shift();
    if (expectedFrame === null) {
      break;
    }

    if (data.length < idx + expectedFrame.length) {
      this._expectedFrames.unshift(expectedFrame);
      break;
    }

    if (expectedFrame === false || expectedFrame === undefined) break;
    var actualFrame = data.slice(idx, idx + expectedFrame.length);
    debug('expected(', expectedFrame.length, '):', expectedFrame.toString('hex'));
    debug('  actual(', actualFrame.length, '):', actualFrame.toString('hex'));
    expect(actualFrame).to.eql(expectedFrame);
    if (this._expectedFrames[0] === false) break;
    if (idx >= data.length) break;
    idx += expectedFrame.length;
  }

  this._seenFrames.push(new BufferList(data));
  this._sendNextResponse();
};

MockServer.prototype.teardown = function() {
  var self = this;
{'fraction_non_alphanumeric': 0.17143776133805083, 'fraction_numerical': 0.004985525892569958, 'mean_word_length': 3.1322259136212622, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4089620', 'n_tokens_mistral': 1916, 'n_tokens_neox': 1863, 'n_words': 371}