<commit_before>/* eslint-env mocha */

'use strict'

const { Grape } = require('./../')
const assert = require('assert')

describe('service announce', () => {
  it('should find services', (done) => {
    const {grape1, grape2, stop} = createTwoGrapes()

    grape1.on('ready', () => {
      grape1.announce('rest:util:net', 1337, () => {})
    })

    grape2.on('announce', () => {
      grape2.lookup('rest:util:net', (err, res) => {
        assert.equal(err, null)
        assert.deepEqual(res, [ '127.0.0.1:1337' ])
        stop(done)
      })
    })
  }).timeout(5000)

  it('should remove outdated services', (done) => {
    const {grape1, grape2, stop} = createTwoGrapes()

    grape1.on('ready', () => {
      grape1.announce('rest:util:net', 1337, () => {})
    })

    grape2.on('announce', () => {
      grape2.lookup('rest:util:net', (err, res) => {
        assert.equal(err, null)
        assert.deepEqual(res, [ '127.0.0.1:1337' ])
        setTimeout(lookup, 150)
      })
    })

    function lookup () {
      grape2.lookup('rest:util:net', (err, res) => {
        assert.equal(err, null)
        assert.deepEqual(res, [])
        stop(done)
      })
    }
  }).timeout(5000)

  it('should not cache dead peers when doing lookups', (done) => {
    let lookups = 0
    const {grape1, grape2, stop} = createTwoGrapes()

    grape1.on('ready', () => {
      grape1.announce('test', 1337, () => {
        loop()

        function loop () {
          lookup((a, b) => {
            if (!a && !b) {
              assert(lookups > 10)
              stop(done)
              return
            }
            lookups++
            if (a) assert.deepEqual(a, '127.0.0.1:1337')
            if (b) assert.deepEqual(b, '127.0.0.1:1337')
            setTimeout(loop, 5)
          })
        }
      })
    })

    function lookup (cb) {
      grape1.lookup('test', (_, a) => {
        grape2.lookup('test', (_, b) => {
          cb(a[0], b[0])
        })
      })
    }
  })

  it('should not cache dead peers when another one is announcing', (done) => {
    let lookups = 0
    const {grape1, grape2, stop} = createTwoGrapes()

    grape1.on('ready', () => {
      const one = startAnnouncing(grape1, 'test', 2000)
      const two = startAnnouncing(grape2, 'test', 2001)
      grape1.announce('test', 1337, () => {
        setTimeout(loop, 50)
        const dead = '127.0.0.1:1337'

        function loop () {
          lookup((a, b) => {
            if (!a.includes(dead) && !b.includes(dead)) {
              clearInterval(one)
              clearInterval(two)
              assert(lookups > 5)
              stop(done)
              return
            }
            lookups++
            assert(a.includes('127.0.0.1:2000'))
            assert(b.includes('127.0.0.1:2000'))
            assert(a.includes('127.0.0.1:2001'))
            assert(b.includes('127.0.0.1:2001'))
            setTimeout(loop, 5)
          })
        }
      })
    })

    function lookup (cb) {
      grape1.lookup('test', (_, a) => {
        grape2.lookup('test', (_, b) => {
          cb(a, b)
        })
      })
    }
  })
})

function startAnnouncing (grape, name, port) {
  return setInterval(_ => grape.announce(name, port), 20)
}

function createTwoGrapes () {
  const grape1 = new Grape({
    dht_port: 20002,
    dht_bootstrap: [ '127.0.0.1:20001' ],
    api_port: 40001,
    dht_peer_maxAge: 100
  })

  grape1.start(() => {})

  const grape2 = new Grape({
    dht_port: 20001,
    dht_bootstrap: [ '127.0.0.1:20002' ],
    api_port: 30002,
    dht_peer_maxAge: 100
  })

  grape2.start(() => {})

  return {grape1, grape2, stop}

  function stop (done) {
    grape1.stop(_ => {
      grape2.stop(_ => {
        done()
      })
    })
  }
}<commit_msg>add @prdn's test<commit_after>/* eslint-env mocha */

'use strict'

const { Grape } = require('./../')
const assert = require('assert')

describe('service announce', () => {
  it('should find services', (done) => {
    const {grape1, grape2, stop} = createTwoGrapes()

    grape1.on('ready', () => {
      grape1.announce('rest:util:net', 1337, () => {})
    })

    grape2.on('announce', () => {
      grape2.lookup('rest:util:net', (err, res) => {
        assert.equal(err, null)
        assert.deepEqual(res, [ '127.0.0.1:1337' ])
        stop(done)
      })
    })
  }).timeout(5000)

  it('should remove outdated services', (done) => {
    const {grape1, grape2, stop} = createTwoGrapes()

    grape1.on('ready', () => {
      grape1.announce('rest:util:net', 1337, () => {})
    })

    grape2.on('announce', () => {
      grape2.lookup('rest:util:net', (err, res) => {
        assert.equal(err, null)
        assert.deepEqual(res, [ '127.0.0.1:1337' ])
        setTimeout(lookup, 150)
      })
    })

    function lookup () {
      grape2.lookup('rest:util:net', (err, res) => {
        assert.equal(err, null)
        assert.deepEqual(res, [])
        stop(done)
      })
    }
  }).timeout(5000)

  it('should not cache dead peers when doing lookups', (done) => {
    let lookups = 0
    const {grape1, grape2, stop} = createTwoGrapes()

    grape1.on('ready', () => {
      grape1.announce('test', 1337, () => {
        loop()

        function loop () {
          lookup((a, b) => {
            if (!a && !b) {
              assert(lookups > 10)
              stop(done)
              return
            }
            lookups++
            if (a) assert.deepEqual(a, '127.0.0.1:1337')
            if (b) assert.deepEqual(b, '127.0.0.1:1337')
            setTimeout(loop, 5)
          })
        }
      })
    })

    function lookup (cb) {
      grape1.lookup('test', (_, a) => {
        grape2.lookup('test', (_, b) => {
          cb(a[0], b[0])
        })
      })
    }
  })

  it('should not cache dead peers when another one is announcing', (done) => {
    let lookups = 0
    const {grape1, grape2, stop} = createTwoGrapes()

    grape1.on('ready', () => {
      const one = startAnnouncing(grape1, 'test', 2000)
      const two = startAnnouncing(grape2, 'test', 2001)
      grape1.announce('test', 1337, () => {
        setTimeout(loop, 50)
        const dead = '127.0.0.1:1337'

        function loop () {
          lookup((a, b) => {
            if (!a.includes(dead) && !b.includes(dead)) {
              clearInterval(one)
              clearInterval(two)
              assert(lookups > 5)
              stop(done)
              return
            }
            lookups++
            assert(a.includes('127.0.0.1:2000'))
            assert(b.includes('127.0.0.1:2000'))
            assert(a.includes('127.0.0.1:2001'))
            assert(b.includes('127.0.0.1:2001'))
            setTimeout(loop, 5)
          })
        }
      })
    })

    function lookup (cb) {
      grape1.lookup('test', (_, a) => {
        grape2.lookup('test', (_, b) => {
          cb(a, b)
        })
      })
    }
  })

  it('should work when services die and come back', function (done) {
    const [g0, g1, g2, g3] = createGrapes(4)
    const interval = startAnnouncing(g0, 'A', 3000)

    g1.on('ready', () => {
      g1.announce('B', 2000, () => {
        setTimeout(run, 50)
        let ticks = 0

        function run () {
          if (!ticks++) {
            lookup((g2l, g3l) => {
              assert.deepEqual(g2l.A, ['127.0.0.1:3000'])
              assert.deepEqual(g3l.A, ['127.0.0.1:3000'])
              assert.deepEqual(g2l.B, ['127.0.0.1:2000'])
              assert.deepEqual(g3l.B, ['127.0.0.1:2000'])
              setTimeout(run, 50)
            })
            return
          }
          if (ticks++ === 5) {
            startAnnouncing(g1, 'B', 2000)
            lookup((g2l, g3l) => {
              assert.deepEqual(g2l.A, ['127.0.0.1:3000'])
              assert.deepEqual(g3l.A, ['127.0.0.1:3000'])
              assert.deepEqual(g2l.B, [])
              assert.deepEqual(g3l.B, [])
              setTimeout(run, 50)
            })
            return
          }
          if (ticks++ === 20) {
            lookup((g2l, g3l) => {
              assert.deepEqual(g2l.A, ['127.0.0.1:3000'])
              assert.deepEqual(g3l.A, ['127.0.0.1:3000'])
              assert.deepEqual(g2l.B, ['127.0.0.1:2000'])
              assert.deepEqual(g3l.B, ['127.0.0.1:2000'])
              setTimeout(run, 50)
              stop()
            })
            return
          }
          setTimeout(run, 50)
        }
      })
    })

    function stop () {
      g0.stop(_ => {
        g1.stop(_ => {
          g2.stop(_ => {
            g3.stop(_ => {
              done()
            })
          })
        })
      })
    }

    function lookup (cb) {
      g2.lookup('A', (_, g2a) => {
        g2.lookup('B', (_, g2b) => {
          g3.lookup('A', (_, g3a) => {
            g3.lookup('B', (_, g3b) => {
              cb({A: g2a, B: g2b}, {A: g3a, B: g3b})
            })
          })
        })
      })
    }
  })
})

function startAnnouncing (grape, name, port) {
  return setInterval(_ => grape.announce(name, port), 20)
}

function createGrapes (n) {
  const grapes = []

  for (let i = 0; i < n; i++) {
    const grape = new Grape({
      dht_port: 20001 + i,
      dht_bootstrap: [ '127.0.0.1:' + (20001 + (i + 1) % 2) ],
      api_port: 40001 + i,
      dht_peer_maxAge: 100
    })

    grape.start(() => {})
    grapes.push(grape)
  }

  return grapes
}

function createTwoGrapes () {
  const [grape1, grape2] = createGrapes(2)
  return {grape1, grape2, stop}

  function stop (done) {
    grape1.stop(_ => {
      grape2.stop(_ => {
        done()
      })
    })
  }
}
{'fraction_non_alphanumeric': 0.18302776322682032, 'fraction_numerical': 0.061707700366684125, 'mean_word_length': 1.7212086659064993, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 31, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6671392', 'n_tokens_mistral': 3730, 'n_tokens_neox': 3378, 'n_words': 590}