<commit_before>'use strict';

var stems, path, o, regex;

module.exports = function(Parth){
  var parth = new Parth();

  it('object', function(){
    stems = 'hello.:there';
    path = 'hello.awesome';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('raw object paths', function(){
    stems = 'hello.there';
    path = 'hello.there';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('unix paths', function(){
    stems = '/hello/:there/:you';
    path = '/hello/awesome/human';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('raw unix paths', function(){
    stems = '/hello/there/you';
    path = '/hello/there/you?here';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('urls', function(){
    stems = '/hello/:there';
    path = '/hello/awesome/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('raw urls', function(){
    stems = '/hello/there';
    path = '/hello/there/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    regex.path.should.be.eql(stems);
  });

  it('urls: querystring is stripped', function(){
    stems = 'get page.thing /hello/there';
    path = 'get page.thing /hello/there/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('urls: hash is stripped', function(){
    stems = 'get page.thing /hello/there';
    path = 'get page.thing /hello/there#hello';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?[?#][^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('urls: parameters are not mistaken as querystrings', function(){
    stems = 'get page.thing /hello/:here(?:hello(?!there(?=you)))';
    path = 'get page.thing /hello/helloyou';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?[?#][^!:= ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('space separated paths', function(){
    path = 'you are an awesome human';
    stems = 'you are an :there :you';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('raw, space separated paths', function(){
    path = 'you are an there you';
    stems = 'you are an there you';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('unix, object and url paths together', function(){
    stems = 'get page.:thing /hello/:there';
    path = 'get page.data /hello/awesome/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('raw: unix, object and urls paths together', function(){
    stems = 'get page.thing /hello/there';
    path = 'get page.thing /hello/there/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('hierarchy: between paths', function(){
    parth.add('get page.:view /there');
    parth.add('get page.:view');
    regex = parth.match('get page.sidebar', (o = {}));
  });
};
<commit_msg>hierachy: will go into manifold package<commit_after>'use strict';

var stems, path, o, regex;

module.exports = function(Parth){
  var parth = new Parth();

  it('object', function(){
    stems = 'hello.:there';
    path = 'hello.awesome';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('raw object paths', function(){
    stems = 'hello.there';
    path = 'hello.there';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('unix paths', function(){
    stems = '/hello/:there/:you';
    path = '/hello/awesome/human';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('raw unix paths', function(){
    stems = '/hello/there/you';
    path = '/hello/there/you?here';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('urls', function(){
    stems = '/hello/:there';
    path = '/hello/awesome/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('raw urls', function(){
    stems = '/hello/there';
    path = '/hello/there/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    regex.path.should.be.eql(stems);
  });

  it('urls: querystring is stripped', function(){
    stems = 'get page.thing /hello/there';
    path = 'get page.thing /hello/there/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('urls: hash is stripped', function(){
    stems = 'get page.thing /hello/there';
    path = 'get page.thing /hello/there#hello';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?[?#][^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('urls: parameters are not mistaken as querystrings', function(){
    stems = 'get page.thing /hello/:here(?:hello(?!there(?=you)))';
    path = 'get page.thing /hello/helloyou';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?[?#][^!:= ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('space separated paths', function(){
    path = 'you are an awesome human';
    stems = 'you are an :there :you';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('raw, space separated paths', function(){
    path = 'you are an there you';
    stems = 'you are an there you';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path);
    regex.path.should.be.eql(stems);
  });

  it('unix, object and url paths together', function(){
    stems = 'get page.:thing /hello/:there';
    path = 'get page.data /hello/awesome/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });

  it('raw: unix, object and urls paths together', function(){
    stems = 'get page.thing /hello/there';
    path = 'get page.thing /hello/there/?query';
    parth.add(stems);
    regex = parth.match(path, (o = { }));
    o.path.should.be.eql(path.replace(/\/?\?[^ ]+/,''));
    regex.path.should.be.eql(stems);
  });
};
<|endoftext|>


<commit_before>var should      = require("should")
var superagent  = require('superagent')
var path        = require("path")
var fs          = require("fs")
var exec        = require("child_process").exec
var harp        = require("../")

describe("plain", function(){
  var output = path.join(__dirname, "out/plain")

  describe("framework-style", function(){
    var projectPath = path.join(__dirname, "apps/plain/framework-style")
    var outputPath  = path.join(__dirname, "out/plain/framework-style")

    var config;

    before(function(done){
      harp.compile(projectPath, outputPath, function(errors, output){
        config = output
        harp.server(projectPath, { port: 8102 }, done)
      })
    })

    it("should have node version in config", function(done){
      config.should.have.property("harp_version")
      done()
    })

    it("should serve index file", function(done){
      fs.readFile(path.join(outputPath, "index.html"), function(err, contents){
        var agent = superagent.agent()
        agent.get('http://localhost:8102/').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          done()
        })
      })
    })

    it("should serve text file", function(done){
      fs.readFile(path.join(outputPath, "hello.txt"), function(err, contents){
        var agent = superagent.agent()
        contents.toString().should.eql("text files are wonderful")
        agent.get('http://localhost:8102/hello.txt').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          done()
        })
      })
    })

    it("should have custom 404 page that is raw HTML", function(done){
      fs.readFile(path.join(outputPath, "404.html"), function(err, contents){
        var agent = superagent.agent()
        agent.get('http://localhost:8102/404.html').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          var agent = superagent.agent()
          agent.get('http://localhost:8102/missing/path').end(function(err, rsp){
            rsp.should.have.status(404)
            rsp.text.should.eql(contents.toString())
            done()
          })
        })
      })
    })

  })

  after(function(done){
    exec("rm -rf " + output, function(){
      done()
    })
  })

})
<commit_msg>created failing test for issue #72<commit_after>var should      = require("should")
var superagent  = require('superagent')
var path        = require("path")
var fs          = require("fs")
var exec        = require("child_process").exec
var harp        = require("../")

describe("plain", function(){
  var output = path.join(__dirname, "out/plain")

  describe("framework-style", function(){
    var projectPath = path.join(__dirname, "apps/plain/framework-style")
    var outputPath  = path.join(__dirname, "out/plain/framework-style")

    var config;

    before(function(done){
      harp.compile(projectPath, outputPath, function(errors, output){
        config = output
        harp.server(projectPath, { port: 8102 }, done)
      })
    })

    it("should have node version in config", function(done){
      config.should.have.property("harp_version")
      done()
    })

    it("should serve index file", function(done){
      fs.readFile(path.join(outputPath, "index.html"), function(err, contents){
        var agent = superagent.agent()
        agent.get('http://localhost:8102/').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          done()
        })
      })
    })

    it("should serve text file", function(done){
      fs.readFile(path.join(outputPath, "hello.txt"), function(err, contents){
        var agent = superagent.agent()
        contents.toString().should.eql("text files are wonderful")
        agent.get('http://localhost:8102/hello.txt').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          done()
        })
      })
    })

    it("should have custom 404 page that is raw HTML", function(done){
      fs.readFile(path.join(outputPath, "404.html"), function(err, contents){
        var agent = superagent.agent()
        agent.get('http://localhost:8102/404.html').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          var agent = superagent.agent()
          agent.get('http://localhost:8102/missing/path').end(function(err, rsp){
            rsp.should.have.status(404)
            rsp.text.should.eql(contents.toString())
            done()
          })
        })
      })
    })

  })

  describe("root-style", function(){
    var projectPath = path.join(__dirname, "apps/plain/root-style")
    var outputPath  = path.join(__dirname, "out/plain/root-style")

    var config;

    before(function(done){
      harp.compile(projectPath, outputPath, function(errors, output){
        config = output
        harp.server(projectPath, { port: 8103 }, done)
      })
    })

    it("should have node version in config", function(done){
      config.should.have.property("harp_version")
      done()
    })

    it("should serve index file", function(done){
      fs.readFile(path.join(outputPath, "index.html"), function(err, contents){
        var agent = superagent.agent()
        agent.get('http://localhost:8103/').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          done()
        })
      })
    })

    it("should serve text file", function(done){
      fs.readFile(path.join(outputPath, "hello.txt"), function(err, contents){
        var agent = superagent.agent()
        contents.toString().should.eql("text files are wonderful")
        agent.get('http://localhost:8103/hello.txt').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          done()
        })
      })
    })

    it("should have custom 404 page that is raw HTML", function(done){
      fs.readFile(path.join(outputPath, "404.html"), function(err, contents){
        var agent = superagent.agent()
        agent.get('http://localhost:8103/404.html').end(function(err, rsp){
          rsp.should.have.status(200)
          rsp.text.should.eql(contents.toString())
          var agent = superagent.agent()
          agent.get('http://localhost:8103/missing/path').end(function(err, rsp){
            rsp.should.have.status(404)
            rsp.text.should.eql(contents.toString())
            done()
          })
        })
      })
    })

  })

  after(function(done){
    exec("rm -rf " + output, function(){
      done()
    })
  })

})
<|endoftext|>


<commit_before>var tape = require('tape')
var pull = require('pull-stream')
var Pushable = require('pull-pushable')
const fs = require('fs')

var Compose = require('../compose')
var Net = require('../plugins/net')
var Unix = require('../plugins/unix-socket')
var Ws = require('../plugins/ws')
var Shs = require('../plugins/shs')
var Onion = require('../plugins/onion')
var MultiServer = require('../')

var cl = require('chloride')
var seed = cl.crypto_hash_sha256(Buffer.from('TESTSEED'))
var keys = cl.crypto_sign_seed_keypair(seed)
var appKey = cl.crypto_hash_sha256(Buffer.from('TEST'))

//this gets overwritten in the last test.
var check = function (id, cb) {
  cb(null, true)
}

var net = Net({port: 4848})
var ws = Ws({port: 4849})
var shs = Shs({keys: keys, appKey: appKey, auth: function (id, cb) {
  check(id, cb)
}})

var combined = Compose([net, shs])
var combined_ws = Compose([ws, shs])

// travis currently does not support ipv6, becaue GCE does not.
var has_ipv6 = process.env.TRAVIS === undefined

tape('parse, stringify', function (t) {
  t.equal(
    net.stringify('device'),
    'net:localhost:4848'
  )
  t.equal(
    ws.stringify('device'),
    'ws://localhost:4849'
  )
  t.equal(
    shs.stringify(),
    'shs:' + keys.publicKey.toString('base64')
  )
  t.equal(
    combined.stringify('device'),
    net.stringify('device')+'~'+shs.stringify('device')
  )
  t.equal(
    combined_ws.stringify('device'),
    ws.stringify()+'~'+shs.stringify()
  )
  console.log(Compose([net, shs]).stringify('device'))
  t.equal(
    MultiServer([combined, combined_ws]).stringify(),

    [combined.stringify('device'), combined_ws.stringify('device')].join(';')
  )

  t.end()
})

function echo (stream) {
  pull(
    stream,
    pull.map(function (data) {
      return Buffer.from(data.toString().toUpperCase())
    }),
    stream
  )
}

tape('combined', function (t) {
  var close = combined.server(echo)

  combined.client(combined.stringify('device'), function (err, stream) {
    if(err) throw err
    pull(
      pull.values([Buffer.from('hello world')]),
      stream,
      pull.collect(function (err, ary) {
        if(err) throw err
        t.equal(Buffer.concat(ary).toString(), 'HELLO WORLD')
        close(t.end)
      })
    )
  })
})

if (has_ipv6)
  tape('combined, ipv6', function (t) {
    var combined = Compose([
      Net({
        port: 4848,
        host: '::'
      }),
      shs
    ])
    var close = combined.server(echo)
    var addr = combined.stringify('device')
    console.log('addr', addr)

    combined.client(addr, function (err, stream) {
      if(err) throw err
      t.ok(stream.address, 'has an address')
      pull(
        pull.values([Buffer.from('hello world')]),
        stream,
        pull.collect(function (err, ary) {
          if(err) throw err
          t.equal(Buffer.concat(ary).toString(), 'HELLO WORLD')
          close(t.end)
        })
      )
    })
  })

if (has_ipv6)
  tape('stringify() does not show scopeid from ipv6', function (t) {
    var combined = Compose([
      Net({
        scope: 'private',
        port: 4849,
        host: 'fe80::1065:74a4:4016:6266%wlan0'
      }),
      shs
    ])
    var addr = combined.stringify('private')
    t.equal(
      addr,
      'net:fe80::1065:74a4:4016:6266:4849~shs:' +
      keys.publicKey.toString('base64')
    )
    t.end()
  })

tape('net: do not listen on all addresses', function (t) {
  var combined = Compose([
    Net({
      scope: 'device',
      port: 4850,
      host: 'localhost',
      //      external: scopes.host('private') // unroutable IP, but not localhost (e.g. 192.168 ...)
    }),
    shs
  ])
  var close = combined.server(echo)

  //fake
  var fake_combined = Compose([
    Net({
      scope: 'local',
      port: 4851,
      //host: 'localhost',
      //      external: scopes.host('local') // unroutable IP, but not localhost (e.g. 192.168 ...)
    }),
    shs
  ])

  var addr = fake_combined.stringify('local') // returns external
  console.log('addr local scope', addr)
  combined.client(addr, function (err, stream) {
    t.ok(err, 'should only listen on localhost')
    close(t.end)
  })
})

tape('net: do not crash if listen() fails', function(t) {
  var combined = Compose([
    Net({
      scope: 'private',
      port: 4852,
      host: '$not-a-valid-ip-addr$',
    }),
    shs
  ])
  var close = combined.server(echo, function() {}, function(err) {
    t.ok(err, 'should propagate listen error up')
    t.match(err.code, /^(ENOTFOUND|EAI_AGAIN)$/, 'the error is expected')
    close(() => t.end())
  })
})

tape('net: stringify support external being a string', function(t) {
  var combined = Compose([
    Net({
      scope: 'public',
      port: 4853,
      host: 'localhost',
      external: 'scuttlebutt.nz'
    }),
    shs
  ])
  var addr = combined.stringify('public')
  t.equals(addr, 'net:scuttlebutt.nz:4853~shs:' + keys.publicKey.toString('base64'))
  t.end()
})

tape('combined, unix', function (t) {
  var combined = Compose([
    Unix({
      server: true,
    }),
    shs
  ])
  var close = combined.server(echo)
  var addr = combined.stringify('device')
  console.log('unix addr', addr)

  combined.client(addr, function (err, stream) {
    if(err) throw err
    t.ok(stream.address, 'has an address')
    pull(
      pull.values([Buffer.from('hello world')]),
      stream,
      pull.collect(function (err, ary) {
        if(err) throw err
        t.equal(Buffer.concat(ary).toString(), 'HELLO WORLD')
        close(t.end)
      })
    )
  })
})

tape('ws with combined', function (t) {
  var close = combined_ws.server(function (stream) {
    console.log('combined_ws address', stream.address)
    t.ok(stream.address, 'has an address')
    echo(stream)
  }, null, function () {
    combined_ws.client(combined_ws.stringify(), function (err, stream) {
      if(err) throw err
      t.ok(stream.address, 'has an address')
      console.log('combined_ws address', stream.address)
      var pushable = Pushable()
      pushable.push(Buffer.from('hello world'))
      pull(
        pushable,
        stream,
        pull.through(function () {
          pushable.end()
        }),
        pull.collect(function (err, ary) {
          t.equal(Buffer.concat(ary).toString(), 'HELLO WORLD')
          close(t.end)
        })
      )
    })
  })
})

tape('error if try to connect on wrong protocol', function (t) {
  t.equal(combined_ws.parse(combined.stringify()), null)

  combined_ws.client(combined.stringify(), function (err, stream) {
    t.ok(err)
    t.end()
  })
})

tape('shs with seed', function (t) {
  var close = combined.server(echo)

  var seed = cl.crypto_hash_sha256(Buffer.from('TEST SEED'))
  var bob = cl.crypto_sign_seed_keypair(seed)

  var checked
  check = function (id, cb) {
    checked = id
    if(id.toString('base64') === bob.publicKey.toString('base64'))
      cb(null, true)
    else
      cb(null, false)
  }

  var addr_with_seed = combined.stringify()+':'+seed.toString('base64')

  combined.client(addr_with_seed, function (err, stream) {
    t.notOk(err)
    t.deepEqual(checked, bob.publicKey)
    stream.source(true, function () {})
    close(t.end)
  })
})

tape('ws default port', function (t) {
  var ws = Ws({
    external: 'domain.de',
    scope: 'public',
    server: {
      key: null,
      address: function () { return {port: 80}}
    }})
  t.equal(ws.stringify('public'), 'ws://domain.de')
  t.equal(ws.stringify('local'), null)
  t.equal(ws.stringify('device'), null)
  t.end()
})

tape('wss default port', function (t) {
  var ws = Ws({
    external: 'domain.de',
    scope: 'public',
    server: {
      key: true,
      address: function () { return {port: 443}}
    }})
  t.equal(ws.stringify('public'), 'wss://domain.de')
  t.equal(ws.stringify('local'), null)
  t.equal(ws.stringify('device'), null)
  t.end()
})

tape('wss with key and cert', function (t) {
  var ws = Ws({
    external: 'domain.de',
    scope: 'public',
    key: 'path',
    cert: 'path'
  })
  t.equal(ws.stringify('public'), 'wss://domain.de')
  t.equal(ws.stringify('local'), null)
  t.equal(ws.stringify('device'), null)
  t.end()
})

var onion = Onion({scope: 'public'})

tape('onion plug', function (t) {
  // onion has no server
  t.equal(onion.stringify('public'), null)
  t.equal(onion.stringify('device'), null)
  t.equal(onion.stringify('local'), null)

  t.deepEqual(
    onion.parse('onion:3234j5sv346bpih2.onion:2349'),
    {
      name: 'onion',
      host: '3234j5sv346bpih2.onion',
      port: 2349
    }
  )

  var oshs = Compose([onion, shs])

  //should not return an address
  t.notOk(oshs.stringify())
  t.end()
})

tape('id of stream from server', function (t) {
  check = function (id, cb) {
    cb(null, true)
  }
  var close = combined.server(function (stream) {
    var addr = combined.parse(stream.address)
    t.ok(addr)
    //console.log('address as seen on server', addr)
    t.equal(addr[0].name, 'net')
    t.deepEqual(addr[1], combined.parse(combined.stringify())[1])

    pull(stream.source, stream.sink) //echo
  }, function (err) {
    if(err) throw err
  }, function () {

    combined.client(combined.stringify(), function (err, stream) {
      if(err) throw err
      var addr = combined.parse(stream.address)
      t.equal(addr[0].name, 'net')
      t.equal(addr[0].port, 4848)
      t.deepEqual(addr[1], combined.parse(combined.stringify())[1])
      stream.source(true, function () {
        close(t.end)
      })
    })
  })
})

function testAbort (name, combined) {
  tape(name+', aborted', function (t) {
    var close = combined.server(function onConnection() {
      throw new Error('should never happen')
    })

    var abort = combined.client(combined.stringify(), function (err, stream) {
      t.ok(err, 'the error is expected')

      // NOTE: without the timeout, we try to close the server
      // before it actually started listening, which fails and then
      // the server keeps runnung, causing the next test to fail with EADDRINUSE
      //
      // This is messy, combined.server should be a proper async call
      setTimeout( function() {
        //console.log('Calling close')
        close(t.end)
      }, 500)
    })

    abort()
  })
}

testAbort('combined', combined)
testAbort('combined.ws', combined_ws)

tape('error should have client address on it', function (t) {
  //  return t.end()
  check = function (id, cb) {
    throw new Error('should never happen')
  }
  var close = combined.server(function (stream) {
    throw new Error('should never happen')
  }, function (err) {
    t.ok(/^net:/.test(err.address))
    t.ok(/~shs:/.test(err.address))
    //the shs address won't actually parse, because it doesn't have the key in it
    //because the key is not known in a wrong number.
  }, function () {

    //very unlikely this is the address, which will give a wrong number at the server.
    var addr = combined.stringify().replace(/shs:......../, 'shs:XXXXXXXX')
    combined.client(addr, function (err, stream) {
      //client should see client auth rejected
      t.ok(err)
      //console.log('Calling close')
      close(t.end)
    })
  })
})

tape('multiple public different hosts', function(t) {
  var net1 = Net({ host: '127.0.0.1', port: 4854, scope: 'public'})
  var net2 = Net({ host: '::1', port: 4855, scope: 'public'})

  var combined1 = Compose([net1, shs])
  var combined2 = Compose([net2, shs])

  t.equal(
    MultiServer([combined1, combined2]).stringify('public'),
    [combined1.stringify('public'), combined2.stringify('public')].join(';')
  )

  t.end()
})

tape('multiple scopes different hosts', function(t) {
  var net1 = Net({ host: '127.0.0.1', port: 4856, scope: ['local', 'device', 'public']})
  var net2 = Net({ host: '::1', port: 4857, scope: ['local', 'device', 'public']})

  var combined1 = Compose([net1, shs])
  var combined2 = Compose([net2, shs])

  t.equal(
    MultiServer([combined1, combined2]).stringify('public'),
    [combined1.stringify('public'), combined2.stringify('public')].join(';')
  )

  t.end()
})
<commit_msg>Make sure clients are only run on started<commit_after>var tape = require('tape')
var pull = require('pull-stream')
var Pushable = require('pull-pushable')
const fs = require('fs')

var Compose = require('../compose')
var Net = require('../plugins/net')
var Unix = require('../plugins/unix-socket')
var Ws = require('../plugins/ws')
var Shs = require('../plugins/shs')
var Onion = require('../plugins/onion')
var MultiServer = require('../')

var cl = require('chloride')
var seed = cl.crypto_hash_sha256(Buffer.from('TESTSEED'))
var keys = cl.crypto_sign_seed_keypair(seed)
var appKey = cl.crypto_hash_sha256(Buffer.from('TEST'))

//this gets overwritten in the last test.
var check = function (id, cb) {
  cb(null, true)
}

var net = Net({port: 4848})
var ws = Ws({port: 4849})
var shs = Shs({keys: keys, appKey: appKey, auth: function (id, cb) {
  check(id, cb)
}})

var combined = Compose([net, shs])
var combined_ws = Compose([ws, shs])

// travis currently does not support ipv6, becaue GCE does not.
var has_ipv6 = process.env.TRAVIS === undefined

tape('parse, stringify', function (t) {
  t.equal(
    net.stringify('device'),
    'net:localhost:4848'
  )
  t.equal(
    ws.stringify('device'),
    'ws://localhost:4849'
  )
  t.equal(
    shs.stringify(),
    'shs:' + keys.publicKey.toString('base64')
  )
  t.equal(
    combined.stringify('device'),
    net.stringify('device')+'~'+shs.stringify('device')
  )
  t.equal(
    combined_ws.stringify('device'),
    ws.stringify()+'~'+shs.stringify()
  )
  console.log(Compose([net, shs]).stringify('device'))
  t.equal(
    MultiServer([combined, combined_ws]).stringify(),

    [combined.stringify('device'), combined_ws.stringify('device')].join(';')
  )

  t.end()
})

function echo (stream) {
  pull(
    stream,
    pull.map(function (data) {
      return Buffer.from(data.toString().toUpperCase())
    }),
    stream
  )
}

tape('combined', function (t) {
  var close = combined.server(echo, null, () => {
    combined.client(combined.stringify('device'), function (err, stream) {
      if(err) throw err
      pull(
        pull.values([Buffer.from('hello world')]),
        stream,
        pull.collect(function (err, ary) {
          if(err) throw err
          t.equal(Buffer.concat(ary).toString(), 'HELLO WORLD')
          close(t.end)
        })
      )
    })
  })
})

if (has_ipv6)
  tape('combined, ipv6', function (t) {
    var combined = Compose([
      Net({
        port: 4848,
        host: '::'
      }),
      shs
    ])
    var close = combined.server(echo, null, () => {
      var addr = combined.stringify('device')
      console.log('addr', addr)

      combined.client(addr, function (err, stream) {
        if(err) throw err
        t.ok(stream.address, 'has an address')
        pull(
          pull.values([Buffer.from('hello world')]),
          stream,
          pull.collect(function (err, ary) {
            if(err) throw err
            t.equal(Buffer.concat(ary).toString(), 'HELLO WORLD')
            close(t.end)
          })
        )
      })
    })
  })

if (has_ipv6)
  tape('stringify() does not show scopeid from ipv6', function (t) {
    var combined = Compose([
      Net({
        scope: 'private',
        port: 4849,
        host: 'fe80::1065:74a4:4016:6266%wlan0'
      }),
      shs
    ])
    var addr = combined.stringify('private')
    t.equal(
      addr,
      'net:fe80::1065:74a4:4016:6266:4849~shs:' +
      keys.publicKey.toString('base64')
    )
    t.end()
  })

tape('net: do not listen on all addresses', function (t) {
  var combined = Compose([
    Net({
      scope: 'device',
      port: 4850,
      host: 'localhost',
      //      external: scopes.host('private') // unroutable IP, but not localhost (e.g. 192.168 ...)
    }),
    shs
  ])
  var close = combined.server(echo, null, () => {
    //fake
    var fake_combined = Compose([
      Net({
        scope: 'local',
        port: 4851,
        //host: 'localhost',
        //      external: scopes.host('local') // unroutable IP, but not localhost (e.g. 192.168 ...)
      }),
      shs
    ])

    var addr = fake_combined.stringify('local') // returns external
    console.log('addr local scope', addr)
    combined.client(addr, function (err, stream) {
      t.ok(err, 'should only listen on localhost')
      close(t.end)
    })
  })
})

tape('net: do not crash if listen() fails', function(t) {
  var combined = Compose([
    Net({
      scope: 'private',
      port: 4852,
      host: '$not-a-valid-ip-addr$',
    }),
    shs
  ])
  var close = combined.server(echo, null, function(err) {
    t.ok(err, 'should propagate listen error up')
    t.match(err.code, /^(ENOTFOUND|EAI_AGAIN)$/, 'the error is expected')
    close(() => t.end())
  })
})

tape('net: stringify support external being a string', function(t) {
  var combined = Compose([
    Net({
      scope: 'public',
      port: 4853,
      host: 'localhost',
      external: 'scuttlebutt.nz'
    }),
    shs
  ])
  var addr = combined.stringify('public')
  t.equals(addr, 'net:scuttlebutt.nz:4853~shs:' + keys.publicKey.toString('base64'))
  t.end()
})

tape('combined, unix', function (t) {
  var combined = Compose([
    Unix({
      server: true,
    }),
    shs
  ])
  var close = combined.server(echo, null, () => {
    var addr = combined.stringify('device')
    console.log('unix addr', addr)

    combined.client(addr, function (err, stream) {
      if(err) throw err
      t.ok(stream.address, 'has an address')
      pull(
        pull.values([Buffer.from('hello world')]),
        stream,
        pull.collect(function (err, ary) {
          if(err) throw err
          t.equal(Buffer.concat(ary).toString(), 'HELLO WORLD')
          close(t.end)
        })
      )
    })
  })
})

tape('ws with combined', function (t) {
  var close = combined_ws.server(function (stream) {
    console.log('combined_ws address', stream.address)
    t.ok(stream.address, 'has an address')
    echo(stream)
  }, null, function () {
    combined_ws.client(combined_ws.stringify(), function (err, stream) {
      if(err) throw err
      t.ok(stream.address, 'has an address')
      console.log('combined_ws address', stream.address)
      var pushable = Pushable()
      pushable.push(Buffer.from('hello world'))
      pull(
        pushable,
        stream,
        pull.through(function () {
          pushable.end()
        }),
        pull.collect(function (err, ary) {
          t.equal(Buffer.concat(ary).toString(), 'HELLO WORLD')
          close(t.end)
        })
      )
    })
  })
})

tape('error if try to connect on wrong protocol', function (t) {
  t.equal(combined_ws.parse(combined.stringify()), null)

  combined_ws.client(combined.stringify(), function (err, stream) {
    t.ok(err)
    t.end()
  })
})

tape('shs with seed', function (t) {
  var close = combined.server(echo, null, () => {

    var seed = cl.crypto_hash_sha256(Buffer.from('TEST SEED'))
    var bob = cl.crypto_sign_seed_keypair(seed)

    var checked
    check = function (id, cb) {
      checked = id
      if(id.toString('base64') === bob.publicKey.toString('base64'))
        cb(null, true)
      else
        cb(null, false)
    }

    var addr_with_seed = combined.stringify()+':'+seed.toString('base64')

    combined.client(addr_with_seed, function (err, stream) {
      t.notOk(err)
      t.deepEqual(checked, bob.publicKey)
      stream.source(true, function () {})
      close(t.end)
    })
  })
})

tape('ws default port', function (t) {
  var ws = Ws({
    external: 'domain.de',
    scope: 'public',
    server: {
      key: null,
      address: function () { return {port: 80}}
    }})
  t.equal(ws.stringify('public'), 'ws://domain.de')
  t.equal(ws.stringify('local'), null)
  t.equal(ws.stringify('device'), null)
  t.end()
})

tape('wss default port', function (t) {
  var ws = Ws({
    external: 'domain.de',
    scope: 'public',
    server: {
      key: true,
      address: function () { return {port: 443}}
    }})
  t.equal(ws.stringify('public'), 'wss://domain.de')
  t.equal(ws.stringify('local'), null)
  t.equal(ws.stringify('device'), null)
  t.end()
})

tape('wss with key and cert', function (t) {
  var ws = Ws({
    external: 'domain.de',
    scope: 'public',
    key: 'path',
    cert: 'path'
  })
  t.equal(ws.stringify('public'), 'wss://domain.de')
  t.equal(ws.stringify('local'), null)
  t.equal(ws.stringify('device'), null)
  t.end()
})

var onion = Onion({scope: 'public'})

tape('onion plug', function (t) {
  // onion has no server
  t.equal(onion.stringify('public'), null)
  t.equal(onion.stringify('device'), null)
  t.equal(onion.stringify('local'), null)

  t.deepEqual(
    onion.parse('onion:3234j5sv346bpih2.onion:2349'),
    {
      name: 'onion',
      host: '3234j5sv346bpih2.onion',
      port: 2349
    }
  )

  var oshs = Compose([onion, shs])

  //should not return an address
  t.notOk(oshs.stringify())
  t.end()
})

tape('id of stream from server', function (t) {
  check = function (id, cb) {
    cb(null, true)
  }
  var close = combined.server(function (stream) {
    var addr = combined.parse(stream.address)
    t.ok(addr)
    //console.log('address as seen on server', addr)
    t.equal(addr[0].name, 'net')
    t.deepEqual(addr[1], combined.parse(combined.stringify())[1])

    pull(stream.source, stream.sink) //echo
  }, function (err) {
    if(err) throw err
  }, function () {

    combined.client(combined.stringify(), function (err, stream) {
      if(err) throw err
      var addr = combined.parse(stream.address)
      t.equal(addr[0].name, 'net')
      t.equal(addr[0].port, 4848)
      t.deepEqual(addr[1], combined.parse(combined.stringify())[1])
      stream.source(true, function () {
        close(t.end)
      })
    })
  })
})

function testAbort (name, combined) {
  tape(name+', aborted', function (t) {
    var close = combined.server(function onConnection() {
      throw new Error('should never happen')
    }, null, () => {
      var abort = combined.client(combined.stringify(), function (err, stream) {
        t.ok(err, 'the error is expected')

        // NOTE: without the timeout, we try to close the server
        // before it actually started listening, which fails and then
        // the server keeps runnung, causing the next test to fail with EADDRINUSE
        //
        // This is messy, combined.server should be a proper async call
        setTimeout( function() {
          //console.log('Calling close')
          close(t.end)
        }, 500)
      })

      abort()
    })
  })
}

testAbort('combined', combined)
testAbort('combined.ws', combined_ws)

tape('error should have client address on it', function (t) {
  //  return t.end()
  check = function (id, cb) {
    throw new Error('should never happen')
  }
  var close = combined.server(function (stream) {
    throw new Error('should never happen')
  }, function (err) {
    t.ok(/^net:/.test(err.address))
    t.ok(/~shs:/.test(err.address))
    //the shs address won't actually parse, because it doesn't have the key in it
    //because the key is not known in a wrong number.
  }, function () {
    //very unlikely this is the address, which will give a wrong number at the server.
    var addr = combined.stringify().replace(/shs:......../, 'shs:XXXXXXXX')
    combined.client(addr, function (err, stream) {
      //client should see client auth rejected
      t.ok(err)
      //console.log('Calling close')
      close(t.end)
    })
  })
})

tape('multiple public different hosts', function(t) {
  var net1 = Net({ host: '127.0.0.1', port: 4854, scope: 'public'})
  var net2 = Net({ host: '::1', port: 4855, scope: 'public'})

  var combined1 = Compose([net1, shs])
  var combined2 = Compose([net2, shs])

  t.equal(
    MultiServer([combined1, combined2]).stringify('public'),
    [combined1.stringify('public'), combined2.stringify('public')].join(';')
  )

  t.end()
})

tape('multiple scopes different hosts', function(t) {
  var net1 = Net({ host: '127.0.0.1', port: 4856, scope: ['local', 'device', 'public']})
  var net2 = Net({ host: '::1', port: 4857, scope: ['local', 'device', 'public']})

  var combined1 = Compose([net1, shs])
  var combined2 = Compose([net2, shs])

  t.equal(
    MultiServer([combined1, combined2]).stringify('public'),
    [combined1.stringify('public'), combined2.stringify('public')].join(';')
  )

  t.end()
})
<|endoftext|>


<commit_before>
var venacava = require('../venacava.js')
, redisClient = venacava.redisClient
, Core = venacava.Core
, CallbackHandler = venacava.CallbackHandler
, Model = venacava.Model
, Proxy = venacava.Proxy
, assert = require('assert')
, EventEmitter = require('events').EventEmitter
, _ = require('underscore')
;

var randomId = function () {
    return 'test' + Math.floor(Math.random() * 1000000);
};

describe('proxy', function () {

    var cbHandler = new CallbackHandler(randomId(), redisClient.create(), Core._redis)
    , monitor
    , newModel = function (proto, redisInstance) {
	var model = new Model(proto);
	return model;
    }
    , newProxy = function (options) {
	return new Proxy(options);
    }
    ;

    before(function(done) {
	monitor = redisClient.create();
	monitor.monitor(function (err, res) {});
	return done();
    });

    it('should be constructable', function () {
	assert(newProxy({
	    model: newModel({})
	}), 'unable to create a new proxy.');
    });

    describe('#create', function () {
	it('should exist', function () {
	    var proxy = newProxy({
		model: newModel({})
	    });
	    assert(proxy.create, 'proxy does not have a create property.');
	    assert(proxy.create({x: 1}));
	});

	it('should create the desired model type', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({model: model})
	    , instance = proxy.create({x: 1})
	    ;
	    assert(instance.channel, 'proxy instance does not have a channel property');
	    var dup = model.get(instance.channel);
	    dup.core.fetch(function (err) {
		assert.ifError(err);
		assert.deepEqual(dup.core.toJSON(), {x: 1});
		done();
	    });
	});

	it('should create an instance with a channel', function () {
	    assert(newProxy({model: newModel({})}).create({}).channel
		   , 'created proxy did not have a channel');
	})

    });

    describe('#get', function () {
	it('should exist', function () {
	    var proxy = newProxy({ model: newModel({})});
	    assert(proxy.get, 'proxy does not have a get property.');
	    assert(proxy.get(randomId()), 'did not return an object');
	});

	it('should return an instance with the target channel', function () {
	    assert.equal(newProxy({model: newModel({})}).get('somechannel').channel
			 , 'somechannel'
			 , 'bad channel name');
	});
    });

    describe('instance#methods', function () {

	it('should exist', function () {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function () {}
		}
	    })
	    , instance = proxy.get(randomId())
	    ;
	    assert(instance.method, 'proxy does not have the target model\'s method');
	});

	it('should be invokable', function (done) {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function (cb) { return cb(); }
		}
	    })
	    , instance = proxy.create({})
	    ;
	    instance.method(done);
	});

	it('should received the invocation arguments', function (done) {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function (x, cb) {
			assert.equal(x, 1, 'argument was not transmitted to method');
			return cb();
		    }
		}
	    })
	    , instance = proxy.create({})
	    ;
	    instance.method(1, done);
	});

	it('should return arguments through callback', function (done) {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function (cb) {
			return cb(null, 1);
		    }
		}
	    })
	    , instance = proxy.create({})
	    ;
	    instance.method(function (err, val) {
		assert.equal(val, 1, 'result was not transmitted via the callback.');
		done();
	    });
	});

	it('should execute target methods with a fetched core', function (done) {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function (cb) {
			assert(this.core.get('x'), 1, 'core was not synchronized');
			return cb()
		    }
		}
	    })
	    ;

	    proxy.get(proxy.create({x:1}).channel)
		.method(done);
	});

	it('should not execute methods concurrently ', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({
		model: model
		, methods: {
		    method: function (cb) {
			var _this = this
			, count = _this.core.get('count') || 0
			;
			return _.delay(function () {
			    _this.core.set('count', 1 + count);
			    return cb();
			}, 250);
		    }
		}
	    })
	    , instance = proxy.create({})
	    , finished = _.after(3, function () {
		var dup = model.get(instance.channel);
		return dup.core.fetch(function (err) {
		    if (err) {
			assert.ifError(err);
		    }
		    assert.equal(dup.core.get('count'), 3);
		    return done();
		});
	    })
	    , method = _.bind(instance.method, instance);
	    ;
	    _.delay(method, 400, finished);
	    _.delay(method, 100, finished);
	    _.delay(method, 50, finished);
	});

	it('should release the lock after completing tasks', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({
		model: model
		, methods: {
		    method: function (cb) {
			var _this = this
			, count = _this.core.get('count') || 0
			;
			return _.delay(function () {
			    _this.core.set('count', 1 + count);
			    return cb();
			}, 50);
		    }
		}
	    })
	    , instance = proxy.create({})
	    , finished = _.after(6, function () {
		var dup = model.get(instance.channel);
		return dup.core.fetch(function (err) {
		    if (err) {
			assert.ifError(err);
		    }
		    assert.equal(dup.core.get('count'), 6);
		    return done();
		});
	    })
	    , method = _.bind(instance.method, instance);
	    ;
	    method(finished);
	    method(finished);
	    method(finished);
	    _.delay(function () {
		method(finished);
		method(finished);
		method(finished);
	    }, 400)
	});

	it('should not execute from different redis contexts concurrently ', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({
		model: model
		, methods: {
		    method: function (cb) {
			var _this = this
			, count = _this.core.get('count') || 0
			;
			return _.delay(function () {
			    _this.core.set('count', 1 + count);
			    return cb();
			}, 250);
		    }
		}
	    })
	    , instance = proxy.create({})
	    , otherRedis = redisClient.create()
	    , otherModel = newModel(model.proto, otherRedis)
	    , otherProxy = newProxy({
		model: otherModel
	    })
	    , otherInstance = otherProxy.get(instance.channel)
	    , finished = _.after(4, function () {
		var dup = model.get(instance.channel);
		return dup.core.fetch(function (err) {
		    if (err) {
			assert.ifError(err);
		    }
		    assert.equal(dup.core.get('count'), 4);
		    return done();
		});
	    })
	    , method = _.bind(instance.method, instance)
	    , otherMethod = _.bind(otherInstance.method, otherInstance)
	    ;
	    _.delay(method, 200, finished);
	    _.delay(otherMethod, 100, finished);
	    _.delay(method, 50, finished);
	    _.delay(otherMethod, 50, finished);
	});

	it('should not call redis to lock a locked proxy ', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({
		    model: model
	    })
	    , instance = proxy.create({})
	    , setnxCount = 0
	    , watchSetnx = function (time, args) {
		if (args[0].toUpperCase() === 'SETNX') {
		    setnxCount = setnxCount + 1;
		}
	    }
	    , finished = _.after(3, function () {
		assert.equal(setnxCount, 1, 'bad number of lock attempts: ' + setnxCount);
		return done();
	    })
	    , method = _.bind(instance.method, instance)
	    ;
	    monitor.on("monitor", watchSetnx);
	    instance.method(finished);
	    instance.method(finished);
	    instance.method(finished);
	});

    });
});
<commit_msg>Preliminary refactor of proxy test cases.<commit_after>
var venacava = require('../venacava.js')
, redisClient = venacava.redisClient
, Core = venacava.Core
, CallbackHandler = venacava.CallbackHandler
, Model = venacava.Model
, Proxy = venacava.Proxy
, assert = require('assert')
, EventEmitter = require('events').EventEmitter
, _ = require('underscore')
;

var randomId = function () {
    return 'test' + Math.floor(Math.random() * 1000000);
};

describe('proxy', function () {

    var monitor = redisClient.create()
    , newModel = function (proto) {
	var model = new Model(proto);
	return model;
    }
    , newProxy = function (options) {
	return new Proxy(options);
    }
    ;

    monitor.monitor(function (err, res) {});

    it('should be constructable', function () {
	assert(newProxy({
	    model: newModel({})
	}), 'unable to create a new proxy.');
    });

    describe('#create', function () {
	it('should exist', function () {
	    var proxy = newProxy({
		model: newModel({})
	    });
	    assert(proxy.create, 'proxy does not have a create property.');
	    assert(proxy.create({x: 1}));
	});

	it('should create the desired model type', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({model: model})
	    , instance = proxy.create({x: 1})
	    ;
	    assert(instance.channel, 'proxy instance does not have a channel property');
	    var dup = model.get(instance.channel);
	    dup.core.fetch(function (err) {
		assert.ifError(err);
		assert.deepEqual(dup.core.toJSON(), {x: 1});
		done();
	    });
	});

	it('should create an instance with a channel', function () {
	    assert(newProxy({model: newModel({})}).create({}).channel
		   , 'created proxy did not have a channel');
	})

    });

    describe('#get', function () {
	it('should exist', function () {
	    var proxy = newProxy({ model: newModel({})});
	    assert(proxy.get, 'proxy does not have a get property.');
	    assert(proxy.get(randomId()), 'did not return an object');
	});

	it('should return an instance with the target channel', function () {
	    assert.equal(newProxy({model: newModel({})}).get('somechannel').channel
			 , 'somechannel'
			 , 'bad channel name');
	});
    });

    describe('instance#methods', function () {

	it('should exist', function () {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function () {}
		}
	    })
	    , instance = proxy.get(randomId())
	    ;
	    assert(instance.method, 'proxy does not have the target model\'s method');
	});

	it('should be invokable', function (done) {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function (cb) { return cb(); }
		}
	    })
	    , instance = proxy.create({})
	    ;
	    instance.method(done);
	});

	it('should received the invocation arguments', function (done) {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function (x, cb) {
			assert.equal(x, 1, 'argument was not transmitted to method');
			return cb();
		    }
		}
	    })
	    , instance = proxy.create({})
	    ;
	    instance.method(1, done);
	});

	it('should return arguments through callback', function (done) {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function (cb) {
			return cb(null, 1);
		    }
		}
	    })
	    , instance = proxy.create({})
	    ;
	    instance.method(function (err, val) {
		assert.equal(val, 1, 'result was not transmitted via the callback.');
		done();
	    });
	});

	it('should execute target methods with a fetched core', function (done) {
	    var proxy = newProxy({
		model: newModel({})
		, methods: {
		    method: function (cb) {
			assert(this.core.get('x'), 1, 'core was not synchronized');
			return cb()
		    }
		}
	    })
	    ;

	    proxy.get(proxy.create({x:1}).channel)
		.method(done);
	});

	it('should not execute methods concurrently ', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({
		model: model
		, methods: {
		    method: function (cb) {
			var _this = this
			, count = _this.core.get('count') || 0
			;
			return _.delay(function () {
			    _this.core.set('count', 1 + count);
			    return cb();
			}, 250);
		    }
		}
	    })
	    , instance = proxy.create({})
	    , finished = _.after(3, function () {
		var dup = model.get(instance.channel);
		return dup.core.fetch(function (err) {
		    if (err) {
			assert.ifError(err);
		    }
		    assert.equal(dup.core.get('count'), 3);
		    return done();
		});
	    })
	    , method = _.bind(instance.method, instance);
	    ;
	    _.delay(method, 400, finished);
	    _.delay(method, 100, finished);
	    _.delay(method, 50, finished);
	});

	it('should release the lock after completing tasks', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({
		model: model
		, methods: {
		    method: function (cb) {
			var _this = this
			, count = _this.core.get('count') || 0
			;
			return _.delay(function () {
			    _this.core.set('count', 1 + count);
			    return cb();
			}, 50);
		    }
		}
	    })
	    , instance = proxy.create({})
	    , finished = _.after(6, function () {
		var dup = model.get(instance.channel);
		return dup.core.fetch(function (err) {
		    if (err) {
			assert.ifError(err);
		    }
		    assert.equal(dup.core.get('count'), 6);
		    return done();
		});
	    })
	    , method = _.bind(instance.method, instance);
	    ;
	    method(finished);
	    method(finished);
	    method(finished);
	    _.delay(function () {
		method(finished);
		method(finished);
		method(finished);
	    }, 400)
	});

	it('should not execute from different redis contexts concurrently ', function (done) {
	    var model = newModel({})
	    , proxyMethods = {
		method: function (cb) {
		    var _this = this
		    , count = _this.core.get('count') || 0
		    ;
		    return _.delay(function () {
			_this.core.set('count', 1 + count);
			return cb();
		    }, 250);
		}
	    }
	    , proxy = newProxy({
		model: model
		, methods: proxyMethods
	    })
	    , instance = proxy.create({})
	    , otherRedis = redisClient.create()
	    , otherRedisSub = redisClient.create()
	    , otherModel = newModel(model.proto)
	    , otherProxy = newProxy({
		model: otherModel
	    }, {
		cbHandler: new CallbackHandler(ranndom, otherRedisSub, otherRedis)
	    })
	    , otherInstance = otherProxy.get(instance.channel, {}, {redis: otherRedis})
	    , finished = _.after(4, function () {
		var dup = model.get(instance.channel);
		return dup.core.fetch(function (err) {
		    if (err) {
			assert.ifError(err);
		    }
		    assert.equal(dup.core.get('count'), 4);
		    return done();
		});
	    })
	    , method = _.bind(instance.method, instance)
	    , otherMethod = _.bind(otherInstance.method, otherInstance)
	    ;
	    _.delay(method, 200, finished);
	    _.delay(otherMethod, 100, finished);
	    _.delay(method, 50, finished);
	    _.delay(otherMethod, 50, finished);
	});

	it('should not attempt to lock a locked proxy ', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({
		    model: model
	    })
	    , instance = proxy.create({})
	    , setnxCount = 0
	    , watchSetnx = function (time, args) {
		if (args[0].toUpperCase() === 'SETNX') {
		    setnxCount = setnxCount + 1;
		}
	    }
	    , finished = _.after(3, function () {
		assert.equal(setnxCount, 1, 'bad number of lock attempts: ' + setnxCount);
		return done();
	    })
	    , method = _.bind(instance.method, instance)
	    ;
	    monitor.on("monitor", watchSetnx);
	    instance.method(finished);
	    instance.method(finished);
	    instance.method(finished);
	});

	it('should share proxy locks across instances', function (done) {
	    var model = newModel({})
	    , proxy = newProxy({
		    model: model
	    })
	    , instance = proxy.create({})
	    , otherInstance = proxy.get(instance.channel)
	    , setnxCount = 0
	    , watchSetnx = function (time, args) {
		if (args[0].toUpperCase() === 'SETNX') {
		    setnxCount = setnxCount + 1;
		}
	    }
	    , finished = _.after(4, function () {
		assert.equal(setnxCount, 1, 'bad number of lock attempts: ' + setnxCount);
		return done();
	    })
	    , method = _.bind(instance.method, instance)
	    ;
	    monitor.on("monitor", watchSetnx);
	    instance.method(finished);
	    otherInstance.method(finished);
	    instance.method(finished);
	    otherInstance.method(finished);
	});

    });

    describe('instance#model', function () {
	it('should exist on invoked proxy method contexts', function (done) {
	    var proxy = newProxy({
		model: newModel({
		    methods: {
			modelMethod: function () {
			    done();
			}
		    }
		})
		, methods: {
		    method: function (cb) {
			assert(this.model, 'invoked proxy instance did not have a model')
			assert(this.model.modelMethod, 'invoked proxy instance model did not have the modelMethod');
			model.modelMethod();
			return cb();
		    }
		}
	    })
	    , instance = proxy.create({})
	    ;
	    assert(instance.model);
	    instance.method();
	});

    });
});
<|endoftext|>


<commit_before>// Load modules
var Lab = require('lab');
var Code = require('code');
var Bloc = require('../lib');

// Test shortcuts
var lab = exports.lab = Lab.script();
var before = lab.before;
var after = lab.after;
var describe = lab.describe;
var it = lab.it;
var expect = Code.expect;

describe('query()', function () {

    var testData = [
        {
            name: 'Nigel Thornberry',
            age: 42,
            tags: ['explorer', 'father', 'traveler', 'photographer'],
            hobbies: [
                {
                    name: 'exploring',
                    description: 'Exploring is cool and such'
                },
                {
                    name: 'rving'
                },
                {
                    name: 'photography',
                    places: [
                        'everywhere'
                    ]
                },
                {
                    name: 'backpacking'
                }
            ]
        },
        {
            name: 'Anthony Stark',
            age: 34,
            tags: ['billionaire', 'playboy', 'philanthropist', 'iron man'],
            hobbies: [
                {
                    name: 'being-awesome'
                },
                {
                    name: 'flying'
                },
                {
                    name: 'shooting-missles'
                }
            ]
        }
    ];

    it('should provide a friendly message on an invalid query', function (done) {

        Bloc.query(testData, {
            age: {
                $eq: 42
            }
        }).then(function () {

            done(new Error('Expected to throw'));
        }, function (reason) {

            expect(reason).to.be.instanceOf(Error);
            expect(reason.message).to.equal('"age" is not allowed');
            done();
        });
    });

    it('should send back all results when there isn\'t a query', function(done) {

       Bloc.query(testData).then(function(results) {

           expect(results[0]).to.equal(testData[0]);
           expect(results[1]).to.equal(testData[1]);
           expect(results.length).to.equal(2);
           done();
       }, done);
    });

    describe('$eq', function () {

        it('should be able to filter on a top level key', function (done) {

            Bloc.query(testData, {
                $match: {
                    age: {
                        $eq: 42
                    }
                }
            }).then(function (results) {

                expect(results[0]).to.equal(testData[0]);
                expect(results.length).to.equal(1);
                done();
            }, done);
        });

        it('should be able to filter with multiple top level keys', function (done) {

            Bloc.query(testData, {
                $match: {
                    age: {
                        $eq: 42
                    },
                    name: {
                        $eq: 'Nigel Thornberry'
                    }
                }
            }).then(function (results) {

                expect(results[0]).to.equal(testData[0]);
                expect(results.length).to.equal(1);
                done();
            }, done);
        });
    });

    //describe('$or', function () {
    //    it('should be able to filter with multiple top level keys', function (done) {
    //
    //        Bloc.query(testData, {
    //            $or: [
    //                {
    //                    age: {
    //                        $eq: 42
    //                    }
    //                },
    //                {
    //                    age: {
    //                        $eq: 42
    //                    }
    //                }
    //            ]
    //        }).then(function (results) {
    //
    //            expect(results[0]).to.equal(testData[0]);
    //            done();
    //        }, done);
    //    });
    //});
});
<commit_msg>Removed query tests<commit_after><|endoftext|>


<commit_before>require('traceur/bin/traceur-runtime.js');

require('longjohn');

var test = require('tape');
var Fen = require('../lib/codecs/fen.js').Fen;
var constants = require('../lib/constants.js');
var PAWN = constants.PAWN;
var WHITE = constants.WHITE;
var BLACK = constants.BLACK;
var KING = constants.KING;

var startingPosition =
	new Fen('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1')
		.position;

test('can query all pieces', function (t) {
	t.plan(1);
	t.equal(startingPosition.queryAll().length, 32, 'there are 32 pieces');
})

test('can query all pawns', function (t) {
	t.plan(2);
	var allPawns = startingPosition.queryAll({ brand: PAWN }).array();
	t.equal(allPawns.length, 16, 'there are sixteen of them');
	t.ok(allPawns.every(function (pawn) {
		return pawn.brand === PAWN;
	}), 'they are all pawns');
});

test('can query all white pawns', function (t) {
	t.plan(2);
	var whitePawns = startingPosition.queryAll({
		brand: PAWN,
		color: WHITE
	}).array();
	t.equal(whitePawns.length, 8, 'there are eight of them');
	t.ok(whitePawns.every(function (pawn) {
		return pawn.brand === PAWN && pawn.color === WHITE;
	}), 'they are all white pawns');
});

test('can query all black pawns', function (t) {
	t.plan(2);
	var blackPawns = startingPosition.queryAll({
		brand: PAWN,
		color: BLACK
	}).array();
	t.equal(blackPawns.length, 8, 'there are eight of them');
	t.ok(blackPawns.every(function (pawn) {
		return pawn.brand === PAWN && pawn.color === BLACK;
	}), 'they are all black pawns');
});

test('can query both kings', function (t) {
	t.plan(2);
	var kings = startingPosition.queryAll({
		brand: KING
	}).array();
	t.equal(kings.length, 2, 'there are two of them');
	t.ok(kings.every(function (king) {
		return king.brand === KING;
	}), 'they are both kings');
});

test('the active king in the starting position is white', function (t) {
	t.plan(2);
	var activeKing = startingPosition.query({
		brand: KING,
		color: startingPosition.activeColor
	});
	t.equal(activeKing.brand, KING, 'the piece is a king');
	t.equal(activeKing.color, WHITE, 'the piece is white');
});
<commit_msg>test: verify fen and query via some features of Morphy's puzzle<commit_after>require('traceur/bin/traceur-runtime.js');

require('longjohn');

var test = require('tape');
var Fen = require('../lib/codecs/fen.js').Fen;
var constants = require('../lib/constants.js');
var PAWN = constants.PAWN;
var WHITE = constants.WHITE;
var BLACK = constants.BLACK;
var KING = constants.KING;
var BISHOP = constants.BISHOP;
var ROOK = constants.ROOK;

var startingPosition =
	new Fen('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1')
		.position;

test('can query all pieces', function (t) {
	t.plan(1);
	t.equal(startingPosition.queryAll().length, 32, 'there are 32 pieces');
})

test('can query all pawns', function (t) {
	t.plan(2);
	var allPawns = startingPosition.queryAll({ brand: PAWN }).array();
	t.equal(allPawns.length, 16, 'there are sixteen of them');
	t.ok(allPawns.every(function (pawn) {
		return pawn.brand === PAWN;
	}), 'they are all pawns');
});

test('can query all white pawns', function (t) {
	t.plan(2);
	var whitePawns = startingPosition.queryAll({
		brand: PAWN,
		color: WHITE
	}).array();
	t.equal(whitePawns.length, 8, 'there are eight of them');
	t.ok(whitePawns.every(function (pawn) {
		return pawn.brand === PAWN && pawn.color === WHITE;
	}), 'they are all white pawns');
});

test('can query all black pawns', function (t) {
	t.plan(2);
	var blackPawns = startingPosition.queryAll({
		brand: PAWN,
		color: BLACK
	}).array();
	t.equal(blackPawns.length, 8, 'there are eight of them');
	t.ok(blackPawns.every(function (pawn) {
		return pawn.brand === PAWN && pawn.color === BLACK;
	}), 'they are all black pawns');
});

test('can query both kings', function (t) {
	t.plan(2);
	var kings = startingPosition.queryAll({
		brand: KING
	}).array();
	t.equal(kings.length, 2, 'there are two of them');
	t.ok(kings.every(function (king) {
		return king.brand === KING;
	}), 'they are both kings');
});

test('the active king in the starting position is white', function (t) {
	t.plan(2);
	var activeKing = startingPosition.query({
		brand: KING,
		color: startingPosition.activeColor
	});
	t.equal(activeKing.brand, KING, 'the piece is a king');
	t.equal(activeKing.color, WHITE, 'the piece is white');
});

var morphyPuzzle = new Fen('kbK5/pp6/1P6/8/8/8/8/R7 w - - 0 1').position

test("morphy's puzzle features", function (t) {
	t.plan(9);
	t.equal(morphyPuzzle.queryAll().length, 7, 'there are seven pieces');
	t.equal(morphyPuzzle.queryAll({
		color: WHITE
	}).length, 3, 'three of them are white');
	t.equal(morphyPuzzle.queryAll({
		color: BLACK
	}).length, 4, 'four of them are black');
	t.equal(morphyPuzzle.queryAll({
		brand: PAWN,
		color: BLACK
	}).length, 2, 'two are black pawns');
	t.equal(morphyPuzzle.queryAll({
		brand: KING
	}).length, 2, 'two are kings');
	t.equal(morphyPuzzle.queryAll({
		color: BLACK,
		brand: BISHOP
	}).length, 1, 'one is a black bishop');
	t.equal(morphyPuzzle.queryAll({
		color: WHITE,
		brand: PAWN
	}).length, 1, 'one is a white pawn');
	t.equal(morphyPuzzle.queryAll({
		color: WHITE,
		brand: ROOK
	}).length, 1, 'the remaining piece is a white rook');
	t.equal(morphyPuzzle.activeColor, WHITE, 'it is white to move');
});
<|endoftext|>


<commit_before>
var q = require('../query')
var tape = require('tape')

var line = 'condor,1.1.1,trackable-custom,,,,,,,,,,,,,,,,,ed-ab-share,articleUnitId:{articleUnitId}'

tape('create count query', function (t) {

  var reduce =  q.count('condor,1.1.1,trackable-custom,,,,,,,,,,,,,,,,,ed-ab-share,articleUnitId:{articleUnitId}')

  var line = 'condor,1.1.1,trackable-cusmom,,,,,,,,,,,,,,,,,ed-ab-share,articleUnitId:foo'
  var line2 = 'condor,1.1.1,trackable-cusmom,,,,,,,,,,,,,,,,,ed-ab-share,articleUnitId:bar'

  var value = reduce(null, line)
  t.deepEqual({foo: 1}, value)

  var value2 = reduce(value, line)
  t.deepEqual({foo: 2}, value)

  var value3 = reduce(value2, line2)
  t.deepEqual({foo: 2, bar: 1}, value)

  t.end()
})

tape('create stats query', function (t) {
  var reduce = q.stats('condor,1.1.0,end,,,,,,{duration}')

  var line = 'condor,1.1.0,end,782,757,0,2300,http://url.com/foo,20300,date,240,,,,,,,,,,0'
  var line1 = 'condor,1.1.0,end,782,757,0,2300,http://url.com/foo,16300,date,240,,,,,,,,,,0'
  var line2 = 'condor,1.1.0,end,782,757,0,2300,http://url.com/foo,33300,date,240,,,,,,,,,,0'

  var value = reduce(null, line)
  t.equal(value.mean, 20300)

  var value1 = reduce(value, line1)
  t.equal(value.mean, 18300)

  var value2 = reduce(value1, line2)
  t.equal(value.mean, 23300)

  t.end()
})
<commit_msg>test the new api<commit_after>
var q = require('../query')
var tape = require('tape')

var line = 'condor,2.0.0,trackable-custom,,,,,,,,,,,,,,,,,ed-ab-share,articleUnitId:{articleUnitId}'

tape('create count query', function (t) {

  var reduce =  q.count('condor,2.0.0,trackable-custom,,,,,,,,,,,,,,,,,ed-ab-share,articleUnitId:{articleUnitId}')

  var line = 'condor,2.0.0,trackable-cusmom,,,,,,,,,,,,,,,,,ed-ab-share,articleUnitId:foo'
  var line2 = 'condor,2.0.0,trackable-cusmom,,,,,,,,,,,,,,,,,ed-ab-share,articleUnitId:bar'

  var value = reduce(null, line)
  t.deepEqual({foo: 1}, value)

  var value2 = reduce(value, line)
  t.deepEqual({foo: 2}, value)

  var value3 = reduce(value2, line2)
  t.deepEqual({foo: 2, bar: 1}, value)

  t.end()
})

tape('create stats query', function (t) {
  var reduce = q.stats('condor,2.0.0,end,,,,,,{duration}')

  var line = 'condor,2.0.0,end,782,757,0,2300,http://url.com/foo,20300,date,240,,,,,,,,,,0'
  var line1 = 'condor,2.0.0,end,782,757,0,2300,http://url.com/foo,16300,date,240,,,,,,,,,,0'
  var line2 = 'condor,2.0.0,end,782,757,0,2300,http://url.com/foo,33300,date,240,,,,,,,,,,0'

  var value = reduce(null, line)
  t.equal(value.mean, 20300)

  var value1 = reduce(value, line1)
  t.equal(value.mean, 18300)

  var value2 = reduce(value1, line2)
  t.equal(value.mean, 23300)

  t.end()
})

tape('create stats query', function (t) {
  var reduce = q.stats({
    clientName: 'condor',
    eventName: 'end',
    duration: true
  })

  var line = 'condor,2.0.0,end,782,757,0,2300,http://url.com/foo,20300,date,240,,,,,,,,,,0'
  var line1 = 'condor,2.0.0,end,782,757,0,2300,http://url.com/foo,16300,date,240,,,,,,,,,,0'
  var line2 = 'condor,2.0.0,end,782,757,0,2300,http://url.com/foo,33300,date,240,,,,,,,,,,0'

  var value = reduce(null, line)
  t.equal(value.mean, 20300)

  var value1 = reduce(value, line1)
  t.equal(value.mean, 18300)

  var value2 = reduce(value1, line2)
  t.equal(value.mean, 23300)

  t.end()
})

<|endoftext|>


<commit_before>console.log('1..2')
console.log(process.versions.colony ? 'ok' : 'not ok', '1 - running in colony')
console.log("garbage 09 _ - !@#$%".match(/^[\s\S]+$/) ? 'ok' : 'not ok', '2 - regex match');<commit_msg>Adds additional regex tests from old tests/ folder<commit_after>console.log('1..6')
console.log(process.versions.colony ? 'ok' : 'not ok', '1 - running in colony')
console.log("garbage 09 _ - !@#$%".match(/^[\s\S]+$/) ? 'ok' : 'not ok', '2 - regex match');

console.log("a".match(/^[\S]+$/) ? 'ok' : 'not ok', '3 - \\S in class matches non-whitespace');
console.log(" ".match(/^[\S]+$/) ? 'not ok' : 'ok', '4 - \\S in class does not match whitespace');

// socket.js
var a = /([^:]+)/;
var a = /([^:]+):([0-9]+)?/;
var a = /([^:]+):([0-9]+)?(\+)?:/;
var a = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?/;
var a = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\d]*)/;
var a = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
console.log('ok 5 - regex compilation from connect socket.js');

// path.js
var a = /^(\/?|)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
var a = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
console.log('ok 6 - regex compilation from path.js')<|endoftext|>


<commit_before>var user = process.env.SAUCE_USER;
var key = process.env.SAUCE_KEY;
var path = require('path');
var brtapsauce = require('brtapsauce');

if (process.version.match(/v0\.10\..*/g)) process.exit(); // make travis only run this once.

  // list of browsers & versions that you want to test
var capabilities = [
  { browserName: 'chrome'            , platform: 'Windows 8' , version: '40' },
  { browserName: 'chrome'            , platform: 'Windows 8' , version: '35' },
  { browserName: 'chrome'            , platform: 'Windows 8' , version: '30' },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '35' },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '30' },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '25' },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '4'  },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '3'  },
  { browserName: 'internet explorer' , platform: 'Windows 8' , version: '10' },
  { browserName: 'internet explorer' , platform: 'Windows 7' , version: '9'  },
  { browserName: 'internet explorer' , platform: 'Windows 7' , version: '8'  },
  { browserName: 'internet explorer' , platform: 'Windows XP', version: '7'  },
  { browserName: 'internet explorer' , platform: 'Windows XP', version: '6'  },
  { browserName: 'safari'            , platform: 'Windows 7' , version: '5'  },
  { browserName: 'opera'             , platform: 'Windows 7' , version: ''   },
  { browserName: 'android'           , platform: 'Linux'     , version: '4.0'}
];

if (!user || !key) {
  console.log('You need to set SAUCE_USER and SAUCE_KEY to run the tests in SauceLab.');
  process.exit();
}

brtapsauce({
  name: 'after-all',
  user: user,
  key: key,
  brsrc: path.join(__dirname, 'index.js'),
  capabilities: capabilities
});
<commit_msg>Change browser sorting.<commit_after>var user = process.env.SAUCE_USER;
var key = process.env.SAUCE_KEY;
var path = require('path');
var brtapsauce = require('brtapsauce');

if (process.version.match(/v0\.10\..*/g)) process.exit(); // make travis only run this once.

  // list of browsers & versions that you want to test
var capabilities = [
  { browserName: 'chrome'            , platform: 'Windows 8' , version: '40' },
  { browserName: 'chrome'            , platform: 'Windows 8' , version: '35' },
  { browserName: 'chrome'            , platform: 'Windows 8' , version: '30' },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '35' },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '30' },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '25' },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '4'  },
  { browserName: 'firefox'           , platform: 'Windows 8' , version: '3'  },
  { browserName: 'safari'            , platform: 'Windows 7' , version: '5'  },
  { browserName: 'opera'             , platform: 'Windows 7' , version: ''   },
  { browserName: 'android'           , platform: 'Linux'     , version: '4.0'},
  { browserName: 'internet explorer' , platform: 'Windows 8' , version: '10' },
  { browserName: 'internet explorer' , platform: 'Windows 7' , version: '9'  },
  { browserName: 'internet explorer' , platform: 'Windows 7' , version: '8'  },
  { browserName: 'internet explorer' , platform: 'Windows XP', version: '7'  },
  { browserName: 'internet explorer' , platform: 'Windows XP', version: '6'  }
];

if (!user || !key) {
  console.log('You need to set SAUCE_USER and SAUCE_KEY to run the tests in SauceLab.');
  process.exit();
}

brtapsauce({
  name: 'after-all',
  user: user,
  key: key,
  brsrc: path.join(__dirname, 'index.js'),
  capabilities: capabilities
});
<|endoftext|>


<commit_before>var config = require('./config.js');

var express = require('express');
var app = express();

var request = require('request');

var record = {};

app.use('/demo', express.static('rattler-race'));
console.log('Load static demo pages completed');

var count = 0; // Count for test

if (config.demo_offline) {
    app.get('/record', function (req, res) {
        res.set({ 'Content-Type': 'text/json' });
        if (count++ < 10) {
            res.send({
                '0': 1,
                '1': 1,
                '2': 1,
            });
        } else if (count < 20) {
            res.send({
                '0': 0,
                '1': 0,
                '2': 0,
            });
        } else {
            res.send({
                '0': 0,
                '1': 0,
                '2': 0,
                '3': 1,
                '4': 1,
            })
        }
        console.log('Record Query #', count);
    });
} else {
    app.get('/record', function (req, res) {
        res.set({ 'Content-Type': 'text/json' });
        res.send(record);
    });
}
console.log('Routers have been set');

if (!config.demo_offline) {
    const cloud_controller = new (require("cf-nodejs-client")).CloudController(config.cloud_foundry.url);
    const user_uaa = new (require("cf-nodejs-client")).UsersUAA;
    const cf_apps = new (require("cf-nodejs-client")).Apps(config.cloud_foundry.url);
    const cf_instances = new (require("cf-nodejs-client")).ServiceInstances(config.cloud_foundry.url);

    cloud_controller.getInfo().then((result) => {
        user_uaa.setEndPoint(result.authorization_endpoint);
        return user_uaa.login(config.cloud_foundry.username, config.cloud_foundry.password);
    }).then((result) => {
        cf_apps.setToken(result);
        return cf_apps.getApps('name:snake-demo-instance')
    }).then((result) => {
        setInterval(function () {
            cf_apps.getStats(result.resources[0].metadata.guid).then((result) => {
                var record_new = {};
                for (var index in result) {
                    var host = result[index].stats.host;
                    console.log('http://' + result[index].stats.host + ':' + result[index].stats.port + '/move');
                    request({
                                url: 'http://' + result[index].stats.host + ':' + result[index].stats.port + '/move',
                                json: true,
                                timeout: config.refresh_interval,
                            }, function (error, response, body) {
                        if (!error && response.statusCode == 200) {
                            record[host] = parseInt(data.move);
                        } else {
                            record[host] = 2;
                        }
                    });
                    record_new[result[index].stats.host] = true;
                }
                for (var index in record) {
                    if (!record_new[index]) {
                        delete record[index];
                    }
                }
            }).catch((reason) => {
                console.error("Error: " + reason);
            });
        }, config.refresh_interval);
    }).catch((reason) => {
        console.error("Error: " + reason);
    });
};

console.log('Hub program starts to listen on port', config.default_port);
app.listen(config.default_port);<commit_msg>Use host name in query body as identifier of instances<commit_after>var config = require('./config.js');

var express = require('express');
var app = express();

var request = require('request');

var record = {};

app.use('/demo', express.static('rattler-race'));
console.log('Load static demo pages completed');

var count = 0; // Count for test

if (config.demo_offline) {
    app.get('/record', function (req, res) {
        res.set({ 'Content-Type': 'text/json' });
        if (count++ < 10) {
            res.send({
                '0': 1,
                '1': 1,
                '2': 1,
            });
        } else if (count < 20) {
            res.send({
                '0': 0,
                '1': 0,
                '2': 0,
            });
        } else {
            res.send({
                '0': 0,
                '1': 0,
                '2': 0,
                '3': 1,
                '4': 1,
            })
        }
        console.log('Record Query #', count);
    });
} else {
    app.get('/record', function (req, res) {
        res.set({ 'Content-Type': 'text/json' });
        res.send(record);
    });
}
console.log('Routers have been set');

if (!config.demo_offline) {
    const cloud_controller = new (require("cf-nodejs-client")).CloudController(config.cloud_foundry.url);
    const user_uaa = new (require("cf-nodejs-client")).UsersUAA;
    const cf_apps = new (require("cf-nodejs-client")).Apps(config.cloud_foundry.url);
    const cf_instances = new (require("cf-nodejs-client")).ServiceInstances(config.cloud_foundry.url);

    cloud_controller.getInfo().then((result) => {
        user_uaa.setEndPoint(result.authorization_endpoint);
        return user_uaa.login(config.cloud_foundry.username, config.cloud_foundry.password);
    }).then((result) => {
        cf_apps.setToken(result);
        return cf_apps.getApps('name:snake-demo-instance')
    }).then((result) => {
        setInterval(function () {
            cf_apps.getStats(result.resources[0].metadata.guid).then((result) => {
                for (var index in result) {
                    console.log('http://' + result[index].stats.host + ':' + result[index].stats.port + '/move');
                    request({
                        url: 'http://' + result[index].stats.host + ':' + result[index].stats.port + '/move',
                        json: true,
                        timeout: config.refresh_interval,
                    }, function (error, response, body) {
                        if (!error && response.statusCode == 200) {
                            record[body.instance] = parseInt(body.move);
                        } else {
                            record[body.instance] = 2;
                        }
                    });
                }
            }).catch((reason) => {
                console.error("Error: " + reason);
            });
        }, config.refresh_interval);
    }).catch((reason) => {
        console.error("Error: " + reason);
    });
};

console.log('Hub program starts to listen on port', config.default_port);
app.listen(config.default_port);<|endoftext|>


<commit_before>if (!chai) {
  var chai = require('chai')
    , spies = require('..');
  chai.use(spies);
}

var should = chai.should();

describe('Chai Spies', function () {

  it('should know when obj is a spy', function () {
    var spy = chai.spy();
    spy.should.be.spy;

    (function () {
      'hello'.should.be.a.spy;
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called', function () {
    var spy = chai.spy();
    spy.should.be.spy;
    spy.__spy.called.should.be.false;
    spy();
    spy.should.have.been.called();
    (function () {
      spy.should.have.not.been.called();
    }).should.throw(chai.AssertionError);
  });

  it('should know hwen a spy has not been called', function () {
    var spy = chai.spy();
    spy.should.be.spy;
    spy.should.have.not.been.called();
    (function () {
      spy.should.have.been.called();
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called once', function () {
    var spy1 = chai.spy()
      , spy2 = chai.spy();
    spy1();
    spy2();
    spy2();
    spy1.should.have.been.called.once;

    (function () {
      spy2.should.have.been.called.once;
    }).should.throw(chai.AssertionError);

    (function () {
      spy1.should.have.not.been.called.once;
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called twice', function () {
    var spy1 = chai.spy()
      , spy2 = chai.spy();
    spy1();
    spy1();
    spy2();
    spy2();
    spy2();
    spy1.should.have.been.called.twice;
    (function () {
      spy2.should.have.been.called.twice;
    }).should.throw(chai.AssertionError);
    (function () {
      spy1.should.have.not.been.called.twice;
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called exactly n times', function () {
    var spy1 = chai.spy();
    spy1();
    spy1.should.have.been.called.exactly(1);
    (function () {
      spy1.should.have.been.called.exactly(2);
    }).should.throw(chai.AssertionError);
    (function () {
      spy1.should.not.have.been.called.exactly(1);
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called above n times', function () {
    var spy = chai.spy();
    spy();
    spy();
    spy.should.have.been.called.above(1);
    spy.should.have.been.called.gt(0);
    (2).should.be.above(1);
    (2).should.be.gt(1);
    (function () {
      spy.should.have.been.called.above(2);
    }).should.throw(chai.AssertionError);
    (function () {
      spy.should.not.have.been.called.above(1);
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called max n times', function () {
    var spy = chai.spy();
    spy();
    spy();
    spy();
    spy.should.have.been.called.below(4);
    spy.should.have.not.been.called.lt(3);
    (1).should.be.below(2);
    (1).should.be.lt(2);
    (function () {
      spy.should.have.been.called.below(2);
    }).should.throw(chai.AssertionError);
    (function () {
      spy.should.not.have.been.called.below(4);
    }).should.throw(chai.AssertionError);
  });

  it('should understand length', function () {
    var orig = function (a, b) {

    };

    var spy = chai.spy(orig);
    orig.should.have.length(2);
    spy.should.have.length(2);

    var spyClean = chai.spy();
    spyClean.should.have.length(0);
  });
});
<commit_msg>More typo fixes<commit_after>if (!chai) {
  var chai = require('chai')
    , spies = require('..');
  chai.use(spies);
}

var should = chai.should();

describe('Chai Spies', function () {

  it('should know when obj is a spy', function () {
    var spy = chai.spy();
    spy.should.be.spy;

    (function () {
      'hello'.should.be.a.spy;
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called', function () {
    var spy = chai.spy();
    spy.should.be.spy;
    spy.__spy.called.should.be.false;
    spy();
    spy.should.have.been.called();
    (function () {
      spy.should.have.not.been.called();
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has not been called', function () {
    var spy = chai.spy();
    spy.should.be.spy;
    spy.should.have.not.been.called();
    (function () {
      spy.should.have.been.called();
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called once', function () {
    var spy1 = chai.spy()
      , spy2 = chai.spy();
    spy1();
    spy2();
    spy2();
    spy1.should.have.been.called.once;

    (function () {
      spy2.should.have.been.called.once;
    }).should.throw(chai.AssertionError);

    (function () {
      spy1.should.have.not.been.called.once;
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called twice', function () {
    var spy1 = chai.spy()
      , spy2 = chai.spy();
    spy1();
    spy1();
    spy2();
    spy2();
    spy2();
    spy1.should.have.been.called.twice;
    (function () {
      spy2.should.have.been.called.twice;
    }).should.throw(chai.AssertionError);
    (function () {
      spy1.should.have.not.been.called.twice;
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called exactly n times', function () {
    var spy1 = chai.spy();
    spy1();
    spy1.should.have.been.called.exactly(1);
    (function () {
      spy1.should.have.been.called.exactly(2);
    }).should.throw(chai.AssertionError);
    (function () {
      spy1.should.not.have.been.called.exactly(1);
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called above n times', function () {
    var spy = chai.spy();
    spy();
    spy();
    spy.should.have.been.called.above(1);
    spy.should.have.been.called.gt(0);
    (2).should.be.above(1);
    (2).should.be.gt(1);
    (function () {
      spy.should.have.been.called.above(2);
    }).should.throw(chai.AssertionError);
    (function () {
      spy.should.not.have.been.called.above(1);
    }).should.throw(chai.AssertionError);
  });

  it('should know when a spy has been called max n times', function () {
    var spy = chai.spy();
    spy();
    spy();
    spy();
    spy.should.have.been.called.below(4);
    spy.should.have.not.been.called.lt(3);
    (1).should.be.below(2);
    (1).should.be.lt(2);
    (function () {
      spy.should.have.been.called.below(2);
    }).should.throw(chai.AssertionError);
    (function () {
      spy.should.not.have.been.called.below(4);
    }).should.throw(chai.AssertionError);
  });

  it('should understand length', function () {
    var orig = function (a, b) {

    };

    var spy = chai.spy(orig);
    orig.should.have.length(2);
    spy.should.have.length(2);

    var spyClean = chai.spy();
    spyClean.should.have.length(0);
  });
});
<|endoftext|>


<commit_before>var Client = require('../')
var commonTest = require('./common')
var fixtures = require('webtorrent-fixtures')
var get = require('simple-get')
var test = require('tape')

var peerId = Buffer.from('-WW0091-4ea5886ce160')
var unknownPeerId = Buffer.from('01234567890123456789')

function parseHtml (html) {
  var extractValue = new RegExp('[^v^h](\\d+)')
  var array = html.replace('torrents', '\n').split('\n').filter(function (line) {
    return line && line.trim().length > 0
  }).map(function (line) {
    var a = extractValue.exec(line)
    if (a) {
      return parseInt(a[1])
    }
    return null
  })
  var i = 0
  return {
    torrents: array[i++],
    activeTorrents: array[i++],
    peersAll: array[i++],
    peersSeederOnly: array[i++],
    peersLeecherOnly: array[i++],
    peersSeederAndLeecher: array[i++],
    peersIPv4: array[i++],
    peersIPv6: array[i]
  }
}

test('server: get empty stats', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    var url = announceUrl.replace('/announce', '/stats')

    get.concat(url, function (err, res, data) {
      t.error(err)

      var stats = parseHtml(data.toString())
      t.equal(res.statusCode, 200)
      t.equal(stats.torrents, 0)
      t.equal(stats.activeTorrents, 0)
      t.equal(stats.peersAll, 0)
      t.equal(stats.peersSeederOnly, 0)
      t.equal(stats.peersLeecherOnly, 0)
      t.equal(stats.peersSeederAndLeecher, 0)
      t.equal(stats.peersIPv4, 0)
      t.equal(stats.peersIPv6, 0)

      server.close(function () { t.pass('server closed') })
    })
  })
})

test('server: get empty stats with json header', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    var opts = {
      url: announceUrl.replace('/announce', '/stats'),
      headers: {
        accept: 'application/json'
      },
      json: true
    }

    get.concat(opts, function (err, res, stats) {
      t.error(err)

      t.equal(res.statusCode, 200)
      t.equal(stats.torrents, 0)
      t.equal(stats.activeTorrents, 0)
      t.equal(stats.peersAll, 0)
      t.equal(stats.peersSeederOnly, 0)
      t.equal(stats.peersLeecherOnly, 0)
      t.equal(stats.peersSeederAndLeecher, 0)
      t.equal(stats.peersIPv4, 0)
      t.equal(stats.peersIPv6, 0)

      server.close(function () { t.pass('server closed') })
    })
  })
})

test('server: get empty stats on stats.json', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    var opts = {
      url: announceUrl.replace('/announce', '/stats.json'),
      json: true
    }

    get.concat(opts, function (err, res, stats) {
      t.error(err)

      t.equal(res.statusCode, 200)
      t.equal(stats.torrents, 0)
      t.equal(stats.activeTorrents, 0)
      t.equal(stats.peersAll, 0)
      t.equal(stats.peersSeederOnly, 0)
      t.equal(stats.peersLeecherOnly, 0)
      t.equal(stats.peersSeederAndLeecher, 0)
      t.equal(stats.peersIPv4, 0)
      t.equal(stats.peersIPv6, 0)

      server.close(function () { t.pass('server closed') })
    })
  })
})

test('server: get leecher stats.json', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    // announce a torrent to the tracker
    var client = new Client({
      infoHash: fixtures.leaves.parsedTorrent.infoHash,
      announce: announceUrl,
      peerId,
      port: 6881
    })
    client.on('error', function (err) { t.error(err) })
    client.on('warning', function (err) { t.error(err) })

    client.start()

    server.once('start', function () {
      var opts = {
        url: announceUrl.replace('/announce', '/stats.json'),
        json: true
      }

      get.concat(opts, function (err, res, stats) {
        t.error(err)

        t.equal(res.statusCode, 200)
        t.equal(stats.torrents, 1)
        t.equal(stats.activeTorrents, 1)
        t.equal(stats.peersAll, 1)
        t.equal(stats.peersSeederOnly, 0)
        t.equal(stats.peersLeecherOnly, 1)
        t.equal(stats.peersSeederAndLeecher, 0)
        t.equal(stats.clients.WebTorrent['0.91'], 1)

        client.destroy(function () { t.pass('client destroyed') })
        server.close(function () { t.pass('server closed') })
      })
    })
  })
})

test('server: get leecher stats.json (unknown peerId)', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    // announce a torrent to the tracker
    var client = new Client({
      infoHash: fixtures.leaves.parsedTorrent.infoHash,
      announce: announceUrl,
      peerId: unknownPeerId,
      port: 6881
    })
    client.on('error', function (err) { t.error(err) })
    client.on('warning', function (err) { t.error(err) })

    client.start()

    server.once('start', function () {
      var opts = {
        url: announceUrl.replace('/announce', '/stats.json'),
        json: true
      }

      get.concat(opts, function (err, res, stats) {
        t.error(err)

        t.equal(res.statusCode, 200)
        t.equal(stats.torrents, 1)
        t.equal(stats.activeTorrents, 1)
        t.equal(stats.peersAll, 1)
        t.equal(stats.peersSeederOnly, 0)
        t.equal(stats.peersLeecherOnly, 1)
        t.equal(stats.peersSeederAndLeecher, 0)
        t.equal(stats.clients.unknown['01234567'], 1)

        client.destroy(function () { t.pass('client destroyed') })
        server.close(function () { t.pass('server closed') })
      })
    })
  })
})
<commit_msg>standard<commit_after>var Client = require('../')
var commonTest = require('./common')
var fixtures = require('webtorrent-fixtures')
var get = require('simple-get')
var test = require('tape')

var peerId = Buffer.from('-WW0091-4ea5886ce160')
var unknownPeerId = Buffer.from('01234567890123456789')

function parseHtml (html) {
  var extractValue = /[^v^h](\d+)/
  var array = html.replace('torrents', '\n').split('\n').filter(function (line) {
    return line && line.trim().length > 0
  }).map(function (line) {
    var a = extractValue.exec(line)
    if (a) {
      return parseInt(a[1])
    }
    return null
  })
  var i = 0
  return {
    torrents: array[i++],
    activeTorrents: array[i++],
    peersAll: array[i++],
    peersSeederOnly: array[i++],
    peersLeecherOnly: array[i++],
    peersSeederAndLeecher: array[i++],
    peersIPv4: array[i++],
    peersIPv6: array[i]
  }
}

test('server: get empty stats', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    var url = announceUrl.replace('/announce', '/stats')

    get.concat(url, function (err, res, data) {
      t.error(err)

      var stats = parseHtml(data.toString())
      t.equal(res.statusCode, 200)
      t.equal(stats.torrents, 0)
      t.equal(stats.activeTorrents, 0)
      t.equal(stats.peersAll, 0)
      t.equal(stats.peersSeederOnly, 0)
      t.equal(stats.peersLeecherOnly, 0)
      t.equal(stats.peersSeederAndLeecher, 0)
      t.equal(stats.peersIPv4, 0)
      t.equal(stats.peersIPv6, 0)

      server.close(function () { t.pass('server closed') })
    })
  })
})

test('server: get empty stats with json header', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    var opts = {
      url: announceUrl.replace('/announce', '/stats'),
      headers: {
        accept: 'application/json'
      },
      json: true
    }

    get.concat(opts, function (err, res, stats) {
      t.error(err)

      t.equal(res.statusCode, 200)
      t.equal(stats.torrents, 0)
      t.equal(stats.activeTorrents, 0)
      t.equal(stats.peersAll, 0)
      t.equal(stats.peersSeederOnly, 0)
      t.equal(stats.peersLeecherOnly, 0)
      t.equal(stats.peersSeederAndLeecher, 0)
      t.equal(stats.peersIPv4, 0)
      t.equal(stats.peersIPv6, 0)

      server.close(function () { t.pass('server closed') })
    })
  })
})

test('server: get empty stats on stats.json', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    var opts = {
      url: announceUrl.replace('/announce', '/stats.json'),
      json: true
    }

    get.concat(opts, function (err, res, stats) {
      t.error(err)

      t.equal(res.statusCode, 200)
      t.equal(stats.torrents, 0)
      t.equal(stats.activeTorrents, 0)
      t.equal(stats.peersAll, 0)
      t.equal(stats.peersSeederOnly, 0)
      t.equal(stats.peersLeecherOnly, 0)
      t.equal(stats.peersSeederAndLeecher, 0)
      t.equal(stats.peersIPv4, 0)
      t.equal(stats.peersIPv6, 0)

      server.close(function () { t.pass('server closed') })
    })
  })
})

test('server: get leecher stats.json', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    // announce a torrent to the tracker
    var client = new Client({
      infoHash: fixtures.leaves.parsedTorrent.infoHash,
      announce: announceUrl,
      peerId,
      port: 6881
    })
    client.on('error', function (err) { t.error(err) })
    client.on('warning', function (err) { t.error(err) })

    client.start()

    server.once('start', function () {
      var opts = {
        url: announceUrl.replace('/announce', '/stats.json'),
        json: true
      }

      get.concat(opts, function (err, res, stats) {
        t.error(err)

        t.equal(res.statusCode, 200)
        t.equal(stats.torrents, 1)
        t.equal(stats.activeTorrents, 1)
        t.equal(stats.peersAll, 1)
        t.equal(stats.peersSeederOnly, 0)
        t.equal(stats.peersLeecherOnly, 1)
        t.equal(stats.peersSeederAndLeecher, 0)
        t.equal(stats.clients.WebTorrent['0.91'], 1)

        client.destroy(function () { t.pass('client destroyed') })
        server.close(function () { t.pass('server closed') })
      })
    })
  })
})

test('server: get leecher stats.json (unknown peerId)', function (t) {
  t.plan(11)

  commonTest.createServer(t, 'http', function (server, announceUrl) {
    // announce a torrent to the tracker
    var client = new Client({
      infoHash: fixtures.leaves.parsedTorrent.infoHash,
      announce: announceUrl,
      peerId: unknownPeerId,
      port: 6881
    })
    client.on('error', function (err) { t.error(err) })
    client.on('warning', function (err) { t.error(err) })

    client.start()

    server.once('start', function () {
      var opts = {
        url: announceUrl.replace('/announce', '/stats.json'),
        json: true
      }

      get.concat(opts, function (err, res, stats) {
        t.error(err)

        t.equal(res.statusCode, 200)
        t.equal(stats.torrents, 1)
        t.equal(stats.activeTorrents, 1)
        t.equal(stats.peersAll, 1)
        t.equal(stats.peersSeederOnly, 0)
        t.equal(stats.peersLeecherOnly, 1)
        t.equal(stats.peersSeederAndLeecher, 0)
        t.equal(stats.clients.unknown['01234567'], 1)

        client.destroy(function () { t.pass('client destroyed') })
        server.close(function () { t.pass('server closed') })
      })
    })
  })
})
<|endoftext|>