First commit
This commit is contained in:
9
node_modules/ldapjs/test/.eslintrc.js
generated
vendored
Normal file
9
node_modules/ldapjs/test/.eslintrc.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest'
|
||||
},
|
||||
|
||||
rules: {
|
||||
'no-shadow': 'off'
|
||||
}
|
||||
}
|
||||
1789
node_modules/ldapjs/test/client.test.js
generated
vendored
Normal file
1789
node_modules/ldapjs/test/client.test.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
53
node_modules/ldapjs/test/controls/control.test.js
generated
vendored
Normal file
53
node_modules/ldapjs/test/controls/control.test.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { BerReader, BerWriter } = require('@ldapjs/asn1')
|
||||
const { Control, getControl } = require('../../lib')
|
||||
|
||||
test('new no args', function (t) {
|
||||
t.ok(new Control())
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('new with args', function (t) {
|
||||
const c = new Control({
|
||||
type: '2.16.840.1.113730.3.4.2',
|
||||
criticality: true
|
||||
})
|
||||
t.ok(c)
|
||||
t.equal(c.type, '2.16.840.1.113730.3.4.2')
|
||||
t.ok(c.criticality)
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('parse', function (t) {
|
||||
const ber = new BerWriter()
|
||||
ber.startSequence()
|
||||
ber.writeString('2.16.840.1.113730.3.4.2')
|
||||
ber.writeBoolean(true)
|
||||
ber.writeString('foo')
|
||||
ber.endSequence()
|
||||
|
||||
const c = getControl(new BerReader(ber.buffer))
|
||||
|
||||
t.ok(c)
|
||||
t.equal(c.type, '2.16.840.1.113730.3.4.2')
|
||||
t.ok(c.criticality)
|
||||
t.equal(c.value.toString('utf8'), 'foo')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('parse no value', function (t) {
|
||||
const ber = new BerWriter()
|
||||
ber.startSequence()
|
||||
ber.writeString('2.16.840.1.113730.3.4.2')
|
||||
ber.endSequence()
|
||||
|
||||
const c = getControl(new BerReader(ber.buffer))
|
||||
|
||||
t.ok(c)
|
||||
t.equal(c.type, '2.16.840.1.113730.3.4.2')
|
||||
t.equal(c.criticality, false)
|
||||
t.notOk(c.value, null)
|
||||
t.end()
|
||||
})
|
||||
104
node_modules/ldapjs/test/corked_emitter.test.js
generated
vendored
Normal file
104
node_modules/ldapjs/test/corked_emitter.test.js
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const CorkedEmitter = require('../lib/corked_emitter')
|
||||
|
||||
function gatherEventSequence (expectedNumber) {
|
||||
const gatheredEvents = []
|
||||
let callback
|
||||
const finished = new Promise(function (resolve) {
|
||||
callback = function (...args) {
|
||||
gatheredEvents.push(...args)
|
||||
if (gatheredEvents.length >= expectedNumber) {
|
||||
// Prevent result mutation after our promise is resolved:
|
||||
resolve(gatheredEvents.slice())
|
||||
}
|
||||
}
|
||||
})
|
||||
return {
|
||||
finished,
|
||||
callback
|
||||
}
|
||||
}
|
||||
|
||||
test('normal emit flow', function (t) {
|
||||
const emitter = new CorkedEmitter()
|
||||
const expectedSequence = [
|
||||
['searchEntry', { data: 'a' }],
|
||||
['searchEntry', { data: 'b' }],
|
||||
['end']
|
||||
]
|
||||
const gatherer = gatherEventSequence(3)
|
||||
emitter.on('searchEntry', function (...args) {
|
||||
gatherer.callback(['searchEntry', ...args])
|
||||
})
|
||||
emitter.on('end', function (...args) {
|
||||
gatherer.callback(['end', ...args])
|
||||
})
|
||||
emitter.emit('searchEntry', { data: 'a' })
|
||||
emitter.emit('searchEntry', { data: 'b' })
|
||||
emitter.emit('end')
|
||||
gatherer.finished.then(function (gatheredEvents) {
|
||||
expectedSequence.forEach(function (expectedEvent, i) {
|
||||
t.equal(JSON.stringify(expectedEvent), JSON.stringify(gatheredEvents[i]))
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
test('reversed listener registration', function (t) {
|
||||
const emitter = new CorkedEmitter()
|
||||
const expectedSequence = [
|
||||
['searchEntry', { data: 'a' }],
|
||||
['searchEntry', { data: 'b' }],
|
||||
['end']
|
||||
]
|
||||
const gatherer = gatherEventSequence(3)
|
||||
// This time, we swap the event listener registrations.
|
||||
// The order of emits should remain unchanged.
|
||||
emitter.on('end', function (...args) {
|
||||
gatherer.callback(['end', ...args])
|
||||
})
|
||||
emitter.on('searchEntry', function (...args) {
|
||||
gatherer.callback(['searchEntry', ...args])
|
||||
})
|
||||
emitter.emit('searchEntry', { data: 'a' })
|
||||
emitter.emit('searchEntry', { data: 'b' })
|
||||
emitter.emit('end')
|
||||
gatherer.finished.then(function (gatheredEvents) {
|
||||
expectedSequence.forEach(function (expectedEvent, i) {
|
||||
t.equal(JSON.stringify(expectedEvent), JSON.stringify(gatheredEvents[i]))
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
test('delayed listener registration', function (t) {
|
||||
const emitter = new CorkedEmitter()
|
||||
const expectedSequence = [
|
||||
['searchEntry', { data: 'a' }],
|
||||
['searchEntry', { data: 'b' }],
|
||||
['end']
|
||||
]
|
||||
const gatherer = gatherEventSequence(3)
|
||||
emitter.emit('searchEntry', { data: 'a' })
|
||||
emitter.emit('searchEntry', { data: 'b' })
|
||||
emitter.emit('end')
|
||||
// The listeners only appear after a brief delay - this simulates
|
||||
// the situation described in https://github.com/ldapjs/node-ldapjs/issues/602
|
||||
// and in https://github.com/ifroz/node-ldapjs/commit/5239f6c68827f2c25b4589089c199d15bb882412
|
||||
setTimeout(function () {
|
||||
emitter.on('end', function (...args) {
|
||||
gatherer.callback(['end', ...args])
|
||||
})
|
||||
emitter.on('searchEntry', function (...args) {
|
||||
gatherer.callback(['searchEntry', ...args])
|
||||
})
|
||||
}, 50)
|
||||
gatherer.finished.then(function (gatheredEvents) {
|
||||
expectedSequence.forEach(function (expectedEvent, i) {
|
||||
t.equal(JSON.stringify(expectedEvent), JSON.stringify(gatheredEvents[i]))
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
53
node_modules/ldapjs/test/errors.test.js
generated
vendored
Normal file
53
node_modules/ldapjs/test/errors.test.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const {
|
||||
LDAPError,
|
||||
ConnectionError,
|
||||
AbandonedError,
|
||||
TimeoutError,
|
||||
ConstraintViolationError,
|
||||
LDAP_OTHER
|
||||
} = require('../lib')
|
||||
|
||||
test('basic error', function (t) {
|
||||
const msg = 'mymsg'
|
||||
const err = new LDAPError(msg, null, null)
|
||||
t.ok(err)
|
||||
t.equal(err.name, 'LDAPError')
|
||||
t.equal(err.code, LDAP_OTHER)
|
||||
t.equal(err.dn, '')
|
||||
t.equal(err.message, msg)
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('exports ConstraintViolationError', function (t) {
|
||||
const msg = 'mymsg'
|
||||
const err = new ConstraintViolationError(msg, null, null)
|
||||
t.ok(err)
|
||||
t.equal(err.name, 'ConstraintViolationError')
|
||||
t.equal(err.code, 19)
|
||||
t.equal(err.dn, '')
|
||||
t.equal(err.message, msg)
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('"custom" errors', function (t) {
|
||||
const errors = [
|
||||
{ name: 'ConnectionError', Func: ConnectionError },
|
||||
{ name: 'AbandonedError', Func: AbandonedError },
|
||||
{ name: 'TimeoutError', Func: TimeoutError }
|
||||
]
|
||||
|
||||
errors.forEach(function (entry) {
|
||||
const msg = entry.name + 'msg'
|
||||
const err = new entry.Func(msg)
|
||||
t.ok(err)
|
||||
t.equal(err.name, entry.name)
|
||||
t.equal(err.code, LDAP_OTHER)
|
||||
t.equal(err.dn, '')
|
||||
t.equal(err.message, msg)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
BIN
node_modules/ldapjs/test/imgs/test.jpg
generated
vendored
Normal file
BIN
node_modules/ldapjs/test/imgs/test.jpg
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 740 B |
116
node_modules/ldapjs/test/issue-845.test.js
generated
vendored
Normal file
116
node_modules/ldapjs/test/issue-845.test.js
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { SearchResultEntry, SearchRequest } = require('@ldapjs/messages')
|
||||
const ldapjs = require('../')
|
||||
|
||||
const server = ldapjs.createServer()
|
||||
|
||||
const SUFFIX = ''
|
||||
const directory = {
|
||||
'dc=example,dc=com': {
|
||||
objectclass: 'example',
|
||||
dc: 'example',
|
||||
cn: 'example'
|
||||
}
|
||||
}
|
||||
|
||||
server.bind(SUFFIX, (req, res, done) => {
|
||||
res.end()
|
||||
return done()
|
||||
})
|
||||
|
||||
server.search(SUFFIX, (req, res, done) => {
|
||||
const dn = req.dn.toString().toLowerCase()
|
||||
|
||||
if (Object.hasOwn(directory, dn) === false) {
|
||||
return done(Error('not in directory'))
|
||||
}
|
||||
|
||||
switch (req.scope) {
|
||||
case SearchRequest.SCOPE_BASE:
|
||||
case SearchRequest.SCOPE_SUBTREE: {
|
||||
res.send(new SearchResultEntry({ objectName: `dc=${req.scopeName}` }))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
res.end()
|
||||
done()
|
||||
})
|
||||
|
||||
tap.beforeEach(t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.listen(0, '127.0.0.1', (err) => {
|
||||
if (err) return reject(err)
|
||||
t.context.url = server.url
|
||||
|
||||
t.context.client = ldapjs.createClient({ url: [server.url] })
|
||||
t.context.searchOpts = {
|
||||
filter: '(&(objectClass=*))',
|
||||
scope: 'sub',
|
||||
attributes: ['dn', 'cn']
|
||||
}
|
||||
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.afterEach(t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
t.context.client.destroy()
|
||||
server.close((err) => {
|
||||
if (err) return reject(err)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('rejects if search not in directory', t => {
|
||||
const { client, searchOpts } = t.context
|
||||
|
||||
client.search('dc=nope', searchOpts, (err, res) => {
|
||||
t.error(err)
|
||||
res.on('error', err => {
|
||||
// TODO: plain error messages should not be lost
|
||||
// This should be fixed in a revamp of the server code.
|
||||
// ~ jsumners 2023-03-08
|
||||
t.equal(err.lde_message, 'Operations Error')
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('base scope matches', t => {
|
||||
const { client, searchOpts } = t.context
|
||||
searchOpts.scope = 'base'
|
||||
|
||||
client.search('dc=example,dc=com', searchOpts, (err, res) => {
|
||||
t.error(err)
|
||||
res.on('error', (err) => {
|
||||
t.error(err)
|
||||
t.end()
|
||||
})
|
||||
res.on('searchEntry', entry => {
|
||||
t.equal(entry.objectName.toString(), 'dc=base')
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('sub scope matches', t => {
|
||||
const { client, searchOpts } = t.context
|
||||
|
||||
client.search('dc=example,dc=com', searchOpts, (err, res) => {
|
||||
t.error(err)
|
||||
res.on('error', (err) => {
|
||||
t.error(err)
|
||||
t.end()
|
||||
})
|
||||
res.on('searchEntry', entry => {
|
||||
t.equal(entry.objectName.toString(), 'dc=subtree')
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
103
node_modules/ldapjs/test/issue-890.test.js
generated
vendored
Normal file
103
node_modules/ldapjs/test/issue-890.test.js
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
'use strict'
|
||||
|
||||
// This test is complicated. It must simulate a server sending an unsolicited,
|
||||
// or a mismatched, message in order to force the client's internal message
|
||||
// tracker to try and find a corresponding sent message that does not exist.
|
||||
// In order to do that, we need to set a high test timeout and wait for the
|
||||
// error message to be logged.
|
||||
|
||||
const tap = require('tap')
|
||||
const ldapjs = require('../')
|
||||
const { SearchResultEntry } = require('@ldapjs/messages')
|
||||
const server = ldapjs.createServer()
|
||||
const SUFFIX = ''
|
||||
|
||||
tap.timeout = 10000
|
||||
|
||||
server.bind(SUFFIX, (res, done) => {
|
||||
res.end()
|
||||
return done()
|
||||
})
|
||||
|
||||
server.search(SUFFIX, (req, res, done) => {
|
||||
const result = new SearchResultEntry({
|
||||
objectName: `dc=${req.scopeName}`
|
||||
})
|
||||
|
||||
// Respond to the search request with a matched response.
|
||||
res.send(result)
|
||||
res.end()
|
||||
|
||||
// After a short delay, send ANOTHER response to the client that will not
|
||||
// be matched by the client's internal tracker.
|
||||
setTimeout(
|
||||
() => {
|
||||
res.send(result)
|
||||
res.end()
|
||||
done()
|
||||
},
|
||||
100
|
||||
)
|
||||
})
|
||||
|
||||
tap.beforeEach(t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.listen(0, '127.0.0.1', (err) => {
|
||||
if (err) return reject(err)
|
||||
|
||||
t.context.logMessages = []
|
||||
t.context.logger = {
|
||||
child () { return this },
|
||||
debug () {},
|
||||
error (...args) {
|
||||
t.context.logMessages.push(args)
|
||||
},
|
||||
trace () {}
|
||||
}
|
||||
|
||||
t.context.url = server.url
|
||||
t.context.client = ldapjs.createClient({
|
||||
url: [server.url],
|
||||
timeout: 5,
|
||||
log: t.context.logger
|
||||
})
|
||||
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.afterEach(t => {
|
||||
return new Promise((resolve, reject) => {
|
||||
t.context.client.destroy()
|
||||
server.close((err) => {
|
||||
if (err) return reject(err)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('handle null messages', t => {
|
||||
const { client, logMessages } = t.context
|
||||
|
||||
// There's no way to get an error from the client when it has received an
|
||||
// unmatched response from the server. So we need to poll our logger instance
|
||||
// and detect when the corresponding error message has been logged.
|
||||
const timer = setInterval(
|
||||
() => {
|
||||
if (logMessages.length > 0) {
|
||||
t.equal(
|
||||
logMessages.some(msg => msg[1] === 'unmatched server message received'),
|
||||
true
|
||||
)
|
||||
clearInterval(timer)
|
||||
t.end()
|
||||
}
|
||||
},
|
||||
100
|
||||
)
|
||||
|
||||
client.search('dc=test', (error) => {
|
||||
t.error(error)
|
||||
})
|
||||
})
|
||||
143
node_modules/ldapjs/test/laundry.test.js
generated
vendored
Normal file
143
node_modules/ldapjs/test/laundry.test.js
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const { getSock, uuid } = require('./utils')
|
||||
const { SearchResultEntry } = require('@ldapjs/messages')
|
||||
const Attribute = require('@ldapjs/attribute')
|
||||
const ldap = require('../lib')
|
||||
|
||||
function search (t, options, callback) {
|
||||
t.context.client.search(t.context.suffix, options, function (err, res) {
|
||||
t.error(err)
|
||||
t.ok(res)
|
||||
let found = false
|
||||
res.on('searchEntry', function (entry) {
|
||||
t.ok(entry)
|
||||
found = true
|
||||
})
|
||||
res.on('end', function () {
|
||||
t.ok(found)
|
||||
if (callback) return callback()
|
||||
return t.end()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
tap.beforeEach((t) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const suffix = `dc=${uuid()}`
|
||||
const server = ldap.createServer()
|
||||
|
||||
t.context.server = server
|
||||
t.context.socketPath = getSock()
|
||||
t.context.suffix = suffix
|
||||
|
||||
server.on('error', err => {
|
||||
server.close(() => reject(err))
|
||||
})
|
||||
|
||||
server.bind('cn=root', function (req, res, next) {
|
||||
res.end()
|
||||
return next()
|
||||
})
|
||||
|
||||
server.search(suffix, function (req, res) {
|
||||
const entry = new SearchResultEntry({
|
||||
entry: 'cn=foo,' + suffix,
|
||||
attributes: Attribute.fromObject({
|
||||
objectclass: ['person', 'top'],
|
||||
cn: 'Pogo Stick',
|
||||
sn: 'Stick',
|
||||
givenname: 'ogo',
|
||||
mail: uuid() + '@pogostick.org'
|
||||
})
|
||||
})
|
||||
|
||||
if (req.filter.matches(entry.attributes)) {
|
||||
res.send(entry)
|
||||
}
|
||||
|
||||
res.end()
|
||||
})
|
||||
|
||||
server.listen(t.context.socketPath, function () {
|
||||
t.context.client = ldap.createClient({
|
||||
socketPath: t.context.socketPath
|
||||
})
|
||||
|
||||
t.context.client.on('error', (err) => {
|
||||
t.context.server.close(() => reject(err))
|
||||
})
|
||||
t.context.client.on('connectError', (err) => {
|
||||
t.context.server.close(() => reject(err))
|
||||
})
|
||||
t.context.client.on('connect', (socket) => {
|
||||
t.context.socket = socket
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.afterEach((t) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!t.context.client) return resolve()
|
||||
t.context.client.unbind(() => {
|
||||
t.context.server.close((err) => {
|
||||
if (err) return reject(err)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('Evolution search filter (GH-3)', function (t) {
|
||||
// This is what Evolution sends, when searching for a contact 'ogo'. Wow.
|
||||
const filter =
|
||||
'(|(cn=ogo*)(givenname=ogo*)(sn=ogo*)(mail=ogo*)(member=ogo*)' +
|
||||
'(primaryphone=ogo*)(telephonenumber=ogo*)(homephone=ogo*)(mobile=ogo*)' +
|
||||
'(carphone=ogo*)(facsimiletelephonenumber=ogo*)' +
|
||||
'(homefacsimiletelephonenumber=ogo*)(otherphone=ogo*)' +
|
||||
'(otherfacsimiletelephonenumber=ogo*)(internationalisdnnumber=ogo*)' +
|
||||
'(pager=ogo*)(radio=ogo*)(telex=ogo*)(assistantphone=ogo*)' +
|
||||
'(companyphone=ogo*)(callbackphone=ogo*)(tty=ogo*)(o=ogo*)(ou=ogo*)' +
|
||||
'(roomnumber=ogo*)(title=ogo*)(businessrole=ogo*)(managername=ogo*)' +
|
||||
'(assistantname=ogo*)(postaladdress=ogo*)(l=ogo*)(st=ogo*)' +
|
||||
'(postofficebox=ogo*)(postalcode=ogo*)(c=ogo*)(homepostaladdress=ogo*)' +
|
||||
'(mozillahomelocalityname=ogo*)(mozillahomestate=ogo*)' +
|
||||
'(mozillahomepostalcode=ogo*)(mozillahomecountryname=ogo*)' +
|
||||
'(otherpostaladdress=ogo*)(jpegphoto=ogo*)(usercertificate=ogo*)' +
|
||||
'(labeleduri=ogo*)(displayname=ogo*)(spousename=ogo*)(note=ogo*)' +
|
||||
'(anniversary=ogo*)(birthdate=ogo*)(mailer=ogo*)(fileas=ogo*)' +
|
||||
'(category=ogo*)(calcaluri=ogo*)(calfburl=ogo*)(icscalendar=ogo*))'
|
||||
|
||||
return search(t, filter)
|
||||
})
|
||||
|
||||
tap.test('GH-49 Client errors on bad attributes', function (t) {
|
||||
const searchOpts = {
|
||||
filter: 'cn=*ogo*',
|
||||
scope: 'one',
|
||||
attributes: 'dn'
|
||||
}
|
||||
return search(t, searchOpts)
|
||||
})
|
||||
|
||||
tap.test('GH-55 Client emits connect multiple times', function (t) {
|
||||
const c = ldap.createClient({
|
||||
socketPath: t.context.socketPath
|
||||
})
|
||||
|
||||
let count = 0
|
||||
c.on('connect', function (socket) {
|
||||
t.ok(socket)
|
||||
count++
|
||||
c.bind('cn=root', 'secret', function (err) {
|
||||
t.error(err)
|
||||
c.unbind(function () {
|
||||
t.equal(count, 1)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
47
node_modules/ldapjs/test/lib/client/message-tracker/ge-window.test.js
generated
vendored
Normal file
47
node_modules/ldapjs/test/lib/client/message-tracker/ge-window.test.js
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { MAX_MSGID } = require('../../../../lib/client/constants')
|
||||
const geWindow = require('../../../../lib/client/message-tracker/ge-window')
|
||||
|
||||
test('comp > (ref in upper window) => true', async t => {
|
||||
const ref = Math.floor(MAX_MSGID / 2) + 10
|
||||
const comp = ref + 10
|
||||
const result = geWindow(ref, comp)
|
||||
t.equal(result, true)
|
||||
})
|
||||
|
||||
test('comp < (ref in upper window) => false', async t => {
|
||||
const ref = Math.floor(MAX_MSGID / 2) + 10
|
||||
const comp = ref - 5
|
||||
const result = geWindow(ref, comp)
|
||||
t.equal(result, false)
|
||||
})
|
||||
|
||||
test('comp > (ref in lower window) => true', async t => {
|
||||
const ref = Math.floor(MAX_MSGID / 2) - 10
|
||||
const comp = ref + 20
|
||||
const result = geWindow(ref, comp)
|
||||
t.equal(result, true)
|
||||
})
|
||||
|
||||
test('comp < (ref in lower window) => false', async t => {
|
||||
const ref = Math.floor(MAX_MSGID / 2) - 10
|
||||
const comp = ref - 5
|
||||
const result = geWindow(ref, comp)
|
||||
t.equal(result, false)
|
||||
})
|
||||
|
||||
test('(max === MAX_MSGID) && (comp > ref) => true', async t => {
|
||||
const ref = MAX_MSGID - Math.floor(MAX_MSGID / 2)
|
||||
const comp = ref + 1
|
||||
const result = geWindow(ref, comp)
|
||||
t.equal(result, true)
|
||||
})
|
||||
|
||||
test('(max === MAX_MSGID) && (comp < ref) => false', async t => {
|
||||
const ref = MAX_MSGID - Math.floor(MAX_MSGID / 2)
|
||||
const comp = ref - 1
|
||||
const result = geWindow(ref, comp)
|
||||
t.equal(result, false)
|
||||
})
|
||||
21
node_modules/ldapjs/test/lib/client/message-tracker/id-generator.test.js
generated
vendored
Normal file
21
node_modules/ldapjs/test/lib/client/message-tracker/id-generator.test.js
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { MAX_MSGID } = require('../../../../lib/client/constants')
|
||||
const idGeneratorFactory = require('../../../../lib/client/message-tracker/id-generator')
|
||||
|
||||
test('starts at 0', async t => {
|
||||
const nextID = idGeneratorFactory()
|
||||
const currentID = nextID()
|
||||
t.equal(currentID, 1)
|
||||
})
|
||||
|
||||
test('handles wrapping around', async t => {
|
||||
const nextID = idGeneratorFactory(MAX_MSGID - 2)
|
||||
|
||||
let currentID = nextID()
|
||||
t.equal(currentID, MAX_MSGID - 1)
|
||||
|
||||
currentID = nextID()
|
||||
t.equal(currentID, 1)
|
||||
})
|
||||
201
node_modules/ldapjs/test/lib/client/message-tracker/index.test.js
generated
vendored
Normal file
201
node_modules/ldapjs/test/lib/client/message-tracker/index.test.js
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
'use strict'
|
||||
|
||||
const tap = require('tap')
|
||||
const messageTrackerFactory = require('../../../../lib/client/message-tracker/')
|
||||
|
||||
tap.test('options', t => {
|
||||
t.test('requires an options object', async t => {
|
||||
try {
|
||||
messageTrackerFactory()
|
||||
} catch (error) {
|
||||
t.match(error, /options object is required/)
|
||||
}
|
||||
|
||||
try {
|
||||
messageTrackerFactory([])
|
||||
} catch (error) {
|
||||
t.match(error, /options object is required/)
|
||||
}
|
||||
|
||||
try {
|
||||
messageTrackerFactory('')
|
||||
} catch (error) {
|
||||
t.match(error, /options object is required/)
|
||||
}
|
||||
|
||||
try {
|
||||
messageTrackerFactory(42)
|
||||
} catch (error) {
|
||||
t.match(error, /options object is required/)
|
||||
}
|
||||
})
|
||||
|
||||
t.test('requires id to be a string', async t => {
|
||||
try {
|
||||
messageTrackerFactory({ id: {} })
|
||||
} catch (error) {
|
||||
t.match(error, /options\.id string is required/)
|
||||
}
|
||||
|
||||
try {
|
||||
messageTrackerFactory({ id: [] })
|
||||
} catch (error) {
|
||||
t.match(error, /options\.id string is required/)
|
||||
}
|
||||
|
||||
try {
|
||||
messageTrackerFactory({ id: 42 })
|
||||
} catch (error) {
|
||||
t.match(error, /options\.id string is required/)
|
||||
}
|
||||
})
|
||||
|
||||
t.test('requires parser to be an object', async t => {
|
||||
try {
|
||||
messageTrackerFactory({ id: 'foo', parser: 'bar' })
|
||||
} catch (error) {
|
||||
t.match(error, /options\.parser object is required/)
|
||||
}
|
||||
|
||||
try {
|
||||
messageTrackerFactory({ id: 'foo', parser: 42 })
|
||||
} catch (error) {
|
||||
t.match(error, /options\.parser object is required/)
|
||||
}
|
||||
|
||||
try {
|
||||
messageTrackerFactory({ id: 'foo', parser: [] })
|
||||
} catch (error) {
|
||||
t.match(error, /options\.parser object is required/)
|
||||
}
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('.pending', t => {
|
||||
t.test('returns 0 for no messages', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
t.equal(tracker.pending, 0)
|
||||
})
|
||||
|
||||
t.test('returns 1 for 1 message', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
tracker.track({}, () => {})
|
||||
t.equal(tracker.pending, 1)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('#abandon', t => {
|
||||
t.test('returns false if message does not exist', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
const result = tracker.abandon(1)
|
||||
t.equal(result, false)
|
||||
})
|
||||
|
||||
t.test('returns true if message is abandoned', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
tracker.track({}, {})
|
||||
const result = tracker.abandon(1)
|
||||
t.equal(result, true)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('#fetch', t => {
|
||||
t.test('returns handler for fetched message', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
tracker.track({}, handler)
|
||||
const { callback: fetched } = tracker.fetch(1)
|
||||
t.equal(fetched, handler)
|
||||
|
||||
function handler () {}
|
||||
})
|
||||
|
||||
t.test('returns handler for fetched abandoned message', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
tracker.track({}, handler)
|
||||
tracker.track({ abandon: 'message' }, () => {})
|
||||
tracker.abandon(1)
|
||||
const { callback: fetched } = tracker.fetch(1)
|
||||
t.equal(fetched, handler)
|
||||
|
||||
function handler () {}
|
||||
})
|
||||
|
||||
t.test('returns null when message does not exist', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
const fetched = tracker.fetch(1)
|
||||
t.equal(fetched, null)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('#purge', t => {
|
||||
t.test('invokes cb for each tracked message', async t => {
|
||||
t.plan(4)
|
||||
let count = 0
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
tracker.track({}, handler1)
|
||||
tracker.track({}, handler2)
|
||||
tracker.purge(cb)
|
||||
|
||||
function cb (msgID, handler) {
|
||||
if (count === 0) {
|
||||
t.equal(msgID, 1)
|
||||
t.equal(handler, handler1)
|
||||
count += 1
|
||||
return
|
||||
}
|
||||
t.equal(msgID, 2)
|
||||
t.equal(handler, handler2)
|
||||
}
|
||||
|
||||
function handler1 () {}
|
||||
function handler2 () {}
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('#remove', t => {
|
||||
t.test('removes from the current track', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
tracker.track({}, () => {})
|
||||
tracker.remove(1)
|
||||
t.equal(tracker.pending, 0)
|
||||
})
|
||||
|
||||
// Not a great test. It exercises the desired code path, but we probably
|
||||
// should expose some insight into the abandoned track.
|
||||
t.test('removes from the abandoned track', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
tracker.track({}, () => {})
|
||||
tracker.track({ abandon: 'message' }, () => {})
|
||||
tracker.abandon(1)
|
||||
tracker.remove(1)
|
||||
t.equal(tracker.pending, 1)
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('#track', t => {
|
||||
t.test('add messageId and tracks message', async t => {
|
||||
const tracker = messageTrackerFactory({ id: 'foo', parser: {} })
|
||||
const msg = {}
|
||||
tracker.track(msg, handler)
|
||||
|
||||
t.same(msg, { messageId: 1 })
|
||||
const { callback: cb } = tracker.fetch(1)
|
||||
t.equal(cb, handler)
|
||||
|
||||
function handler () {}
|
||||
})
|
||||
|
||||
t.end()
|
||||
})
|
||||
64
node_modules/ldapjs/test/lib/client/message-tracker/purge-abandoned.test.js
generated
vendored
Normal file
64
node_modules/ldapjs/test/lib/client/message-tracker/purge-abandoned.test.js
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { MAX_MSGID } = require('../../../../lib/client/constants')
|
||||
const purgeAbandoned = require('../../../../lib/client/message-tracker/purge-abandoned')
|
||||
|
||||
test('clears queue if only one message present', async t => {
|
||||
t.plan(3)
|
||||
const abandoned = new Map()
|
||||
abandoned.set(1, { age: 2, cb })
|
||||
|
||||
purgeAbandoned(2, abandoned)
|
||||
t.equal(abandoned.size, 0)
|
||||
|
||||
function cb (err) {
|
||||
t.equal(err.name, 'AbandonedError')
|
||||
t.equal(err.message, 'client request abandoned')
|
||||
}
|
||||
})
|
||||
|
||||
test('clears queue if multiple messages present', async t => {
|
||||
t.plan(5)
|
||||
const abandoned = new Map()
|
||||
abandoned.set(1, { age: 2, cb })
|
||||
abandoned.set(2, { age: 3, cb })
|
||||
|
||||
purgeAbandoned(4, abandoned)
|
||||
t.equal(abandoned.size, 0)
|
||||
|
||||
function cb (err) {
|
||||
t.equal(err.name, 'AbandonedError')
|
||||
t.equal(err.message, 'client request abandoned')
|
||||
}
|
||||
})
|
||||
|
||||
test('message id has wrappred around', async t => {
|
||||
t.plan(3)
|
||||
const abandoned = new Map()
|
||||
abandoned.set(MAX_MSGID - 1, { age: MAX_MSGID, cb })
|
||||
|
||||
// The "abandon" message was sent with an id of "MAX_MSGID". So the message
|
||||
// that is triggering the purge was the "first" message in the new sequence
|
||||
// of message identifiers.
|
||||
purgeAbandoned(1, abandoned)
|
||||
t.equal(abandoned.size, 0)
|
||||
|
||||
function cb (err) {
|
||||
t.equal(err.name, 'AbandonedError')
|
||||
t.equal(err.message, 'client request abandoned')
|
||||
}
|
||||
})
|
||||
|
||||
test('does not clear if window not met', async t => {
|
||||
t.plan(1)
|
||||
const abandoned = new Map()
|
||||
abandoned.set(1, { age: 2, cb })
|
||||
|
||||
purgeAbandoned(1, abandoned)
|
||||
t.equal(abandoned.size, 1)
|
||||
|
||||
function cb () {
|
||||
t.fail('should not be invoked')
|
||||
}
|
||||
})
|
||||
82
node_modules/ldapjs/test/lib/client/request-queue/enqueue.test.js
generated
vendored
Normal file
82
node_modules/ldapjs/test/lib/client/request-queue/enqueue.test.js
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const enqueue = require('../../../../lib/client/request-queue/enqueue')
|
||||
|
||||
test('rejects new requests if size is exceeded', async t => {
|
||||
const q = { _queue: { size: 5 }, size: 5 }
|
||||
const result = enqueue.call(q, 'foo', 'bar', {}, {})
|
||||
t.notOk(result)
|
||||
})
|
||||
|
||||
test('rejects new requests if queue is frozen', async t => {
|
||||
const q = { _queue: { size: 0 }, size: 5, _frozen: true }
|
||||
const result = enqueue.call(q, 'foo', 'bar', {}, {})
|
||||
t.notOk(result)
|
||||
})
|
||||
|
||||
test('adds a request and returns if no timeout', async t => {
|
||||
const q = {
|
||||
_queue: {
|
||||
size: 0,
|
||||
add (obj) {
|
||||
t.same(obj, {
|
||||
message: 'foo',
|
||||
expect: 'bar',
|
||||
emitter: 'baz',
|
||||
cb: 'bif'
|
||||
})
|
||||
}
|
||||
},
|
||||
_frozen: false,
|
||||
timeout: 0
|
||||
}
|
||||
const result = enqueue.call(q, 'foo', 'bar', 'baz', 'bif')
|
||||
t.ok(result)
|
||||
})
|
||||
|
||||
test('adds a request and returns timer not set', async t => {
|
||||
const q = {
|
||||
_queue: {
|
||||
size: 0,
|
||||
add (obj) {
|
||||
t.same(obj, {
|
||||
message: 'foo',
|
||||
expect: 'bar',
|
||||
emitter: 'baz',
|
||||
cb: 'bif'
|
||||
})
|
||||
}
|
||||
},
|
||||
_frozen: false,
|
||||
timeout: 100,
|
||||
_timer: null
|
||||
}
|
||||
const result = enqueue.call(q, 'foo', 'bar', 'baz', 'bif')
|
||||
t.ok(result)
|
||||
})
|
||||
|
||||
test('adds a request, returns true, and clears queue', t => {
|
||||
// Must not be an async test due to an internal `setTimeout`
|
||||
t.plan(4)
|
||||
const q = {
|
||||
_queue: {
|
||||
size: 0,
|
||||
add (obj) {
|
||||
t.same(obj, {
|
||||
message: 'foo',
|
||||
expect: 'bar',
|
||||
emitter: 'baz',
|
||||
cb: 'bif'
|
||||
})
|
||||
}
|
||||
},
|
||||
_frozen: false,
|
||||
timeout: 5,
|
||||
_timer: 123,
|
||||
freeze () { t.pass() },
|
||||
purge () { t.pass() }
|
||||
}
|
||||
const result = enqueue.call(q, 'foo', 'bar', 'baz', 'bif')
|
||||
t.ok(result)
|
||||
})
|
||||
51
node_modules/ldapjs/test/lib/client/request-queue/flush.test.js
generated
vendored
Normal file
51
node_modules/ldapjs/test/lib/client/request-queue/flush.test.js
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const flush = require('../../../../lib/client/request-queue/flush')
|
||||
|
||||
test('clears timer', async t => {
|
||||
t.plan(2)
|
||||
const q = {
|
||||
_timer: 123,
|
||||
_queue: {
|
||||
values () {
|
||||
return []
|
||||
},
|
||||
clear () {
|
||||
t.pass()
|
||||
}
|
||||
}
|
||||
}
|
||||
flush.call(q)
|
||||
t.equal(q._timer, null)
|
||||
})
|
||||
|
||||
test('invokes callback with parameters', async t => {
|
||||
t.plan(6)
|
||||
const req = {
|
||||
message: 'foo',
|
||||
expect: 'bar',
|
||||
emitter: 'baz',
|
||||
cb: theCB
|
||||
}
|
||||
const q = {
|
||||
_timer: 123,
|
||||
_queue: {
|
||||
values () {
|
||||
return [req]
|
||||
},
|
||||
clear () {
|
||||
t.pass()
|
||||
}
|
||||
}
|
||||
}
|
||||
flush.call(q, (message, expect, emitter, cb) => {
|
||||
t.equal(message, 'foo')
|
||||
t.equal(expect, 'bar')
|
||||
t.equal(emitter, 'baz')
|
||||
t.equal(cb, theCB)
|
||||
})
|
||||
t.equal(q._timer, null)
|
||||
|
||||
function theCB () {}
|
||||
})
|
||||
18
node_modules/ldapjs/test/lib/client/request-queue/purge.test.js
generated
vendored
Normal file
18
node_modules/ldapjs/test/lib/client/request-queue/purge.test.js
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const purge = require('../../../../lib/client/request-queue/purge')
|
||||
|
||||
test('flushes the queue with timeout errors', async t => {
|
||||
t.plan(3)
|
||||
const q = {
|
||||
flush (func) {
|
||||
func('a', 'b', 'c', (err) => {
|
||||
t.ok(err)
|
||||
t.equal(err.name, 'TimeoutError')
|
||||
t.equal(err.message, 'request queue timeout')
|
||||
})
|
||||
}
|
||||
}
|
||||
purge.call(q)
|
||||
})
|
||||
16
node_modules/ldapjs/test/messages/parser.test.js
generated
vendored
Normal file
16
node_modules/ldapjs/test/messages/parser.test.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { Parser } = require('../../lib')
|
||||
|
||||
test('wrong protocol error', function (t) {
|
||||
const p = new Parser()
|
||||
|
||||
p.once('error', function (err) {
|
||||
t.ok(err)
|
||||
t.end()
|
||||
})
|
||||
|
||||
// Send some bogus data to incur an error
|
||||
p.write(Buffer.from([16, 1, 4]))
|
||||
})
|
||||
471
node_modules/ldapjs/test/server.test.js
generated
vendored
Normal file
471
node_modules/ldapjs/test/server.test.js
generated
vendored
Normal file
@ -0,0 +1,471 @@
|
||||
'use strict'
|
||||
|
||||
const net = require('net')
|
||||
const tap = require('tap')
|
||||
const vasync = require('vasync')
|
||||
const vm = require('node:vm')
|
||||
const { getSock } = require('./utils')
|
||||
const ldap = require('../lib')
|
||||
|
||||
const SERVER_PORT = process.env.SERVER_PORT || 1389
|
||||
const SUFFIX = 'dc=test'
|
||||
|
||||
tap.beforeEach(function (t) {
|
||||
// We do not need a `.afterEach` to clean up the sock files because that
|
||||
// is done when the server is destroyed.
|
||||
t.context.sock = getSock()
|
||||
})
|
||||
|
||||
tap.test('basic create', function (t) {
|
||||
const server = ldap.createServer()
|
||||
t.ok(server)
|
||||
t.end()
|
||||
})
|
||||
|
||||
tap.test('connection count', function (t) {
|
||||
const server = ldap.createServer()
|
||||
t.ok(server)
|
||||
server.listen(0, '127.0.0.1', function () {
|
||||
t.ok(true, 'server listening on ' + server.url)
|
||||
|
||||
server.getConnections(function (err, count) {
|
||||
t.error(err)
|
||||
t.equal(count, 0)
|
||||
|
||||
const client = ldap.createClient({ url: server.url })
|
||||
client.on('connect', function () {
|
||||
t.ok(true, 'client connected')
|
||||
server.getConnections(function (err, count) {
|
||||
t.error(err)
|
||||
t.equal(count, 1)
|
||||
client.unbind()
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('properties', function (t) {
|
||||
const server = ldap.createServer()
|
||||
t.equal(server.name, 'LDAPServer')
|
||||
|
||||
// TODO: better test
|
||||
server.maxConnections = 10
|
||||
t.equal(server.maxConnections, 10)
|
||||
|
||||
t.equal(server.url, null, 'url empty before bind')
|
||||
// listen on a random port so we have a url
|
||||
server.listen(0, '127.0.0.1', function () {
|
||||
t.ok(server.url)
|
||||
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('IPv6 URL is formatted correctly', function (t) {
|
||||
const server = ldap.createServer()
|
||||
t.equal(server.url, null, 'url empty before bind')
|
||||
server.listen(0, '::1', function () {
|
||||
t.ok(server.url)
|
||||
t.equal(server.url, 'ldap://[::1]:' + server.port)
|
||||
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('listen on unix/named socket', function (t) {
|
||||
const server = ldap.createServer()
|
||||
server.listen(t.context.sock, function () {
|
||||
t.ok(server.url)
|
||||
t.equal(server.url.split(':')[0], 'ldapi')
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('listen on static port', function (t) {
|
||||
const server = ldap.createServer()
|
||||
server.listen(SERVER_PORT, '127.0.0.1', function () {
|
||||
const addr = server.address()
|
||||
t.equal(addr.port, parseInt(SERVER_PORT, 10))
|
||||
t.equal(server.url, `ldap://127.0.0.1:${SERVER_PORT}`)
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('listen on ephemeral port', function (t) {
|
||||
const server = ldap.createServer()
|
||||
server.listen(0, '127.0.0.1', function () {
|
||||
const addr = server.address()
|
||||
t.ok(addr.port > 0)
|
||||
t.ok(addr.port < 65535)
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('route order', function (t) {
|
||||
function generateHandler (response) {
|
||||
const func = function handler (req, res, next) {
|
||||
res.send({
|
||||
dn: response,
|
||||
attributes: { }
|
||||
})
|
||||
res.end()
|
||||
return next()
|
||||
}
|
||||
return func
|
||||
}
|
||||
|
||||
const server = ldap.createServer()
|
||||
const sock = t.context.sock
|
||||
const dnShort = SUFFIX
|
||||
const dnMed = 'dc=sub,' + SUFFIX
|
||||
const dnLong = 'dc=long,dc=sub,' + SUFFIX
|
||||
|
||||
// Mount routes out of order
|
||||
server.search(dnMed, generateHandler(dnMed))
|
||||
server.search(dnShort, generateHandler(dnShort))
|
||||
server.search(dnLong, generateHandler(dnLong))
|
||||
server.listen(sock, function () {
|
||||
t.ok(true, 'server listen')
|
||||
const client = ldap.createClient({ socketPath: sock })
|
||||
client.on('connect', () => {
|
||||
vasync.forEachParallel({
|
||||
func: runSearch,
|
||||
inputs: [dnShort, dnMed, dnLong]
|
||||
}, function (err) {
|
||||
t.error(err)
|
||||
client.unbind()
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
|
||||
function runSearch (value, cb) {
|
||||
client.search(value, '(objectclass=*)', function (err, res) {
|
||||
t.error(err)
|
||||
t.ok(res)
|
||||
res.on('searchEntry', function (entry) {
|
||||
t.equal(entry.dn.toString(), value)
|
||||
})
|
||||
res.on('end', function () {
|
||||
cb()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('route absent', function (t) {
|
||||
const server = ldap.createServer()
|
||||
const DN_ROUTE = 'dc=base'
|
||||
const DN_MISSING = 'dc=absent'
|
||||
|
||||
server.bind(DN_ROUTE, function (req, res, next) {
|
||||
res.end()
|
||||
return next()
|
||||
})
|
||||
|
||||
server.listen(t.context.sock, function () {
|
||||
t.ok(true, 'server startup')
|
||||
vasync.parallel({
|
||||
funcs: [
|
||||
function presentBind (cb) {
|
||||
const clt = ldap.createClient({ socketPath: t.context.sock })
|
||||
clt.bind(DN_ROUTE, '', function (err) {
|
||||
t.notOk(err)
|
||||
clt.unbind()
|
||||
cb()
|
||||
})
|
||||
},
|
||||
function absentBind (cb) {
|
||||
const clt = ldap.createClient({ socketPath: t.context.sock })
|
||||
clt.bind(DN_MISSING, '', function (err) {
|
||||
t.ok(err)
|
||||
t.equal(err.code, ldap.LDAP_NO_SUCH_OBJECT)
|
||||
clt.unbind()
|
||||
cb()
|
||||
})
|
||||
}
|
||||
]
|
||||
}, function (err) {
|
||||
t.notOk(err)
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('route unbind', function (t) {
|
||||
const server = ldap.createServer()
|
||||
|
||||
server.unbind(function (req, res, next) {
|
||||
t.ok(true, 'server unbind successful')
|
||||
res.end()
|
||||
return next()
|
||||
})
|
||||
|
||||
server.listen(t.context.sock, function () {
|
||||
t.ok(true, 'server startup')
|
||||
const client = ldap.createClient({ socketPath: t.context.sock })
|
||||
client.bind('', '', function (err) {
|
||||
t.error(err, 'client bind error')
|
||||
client.unbind(function (err) {
|
||||
t.error(err, 'client unbind error')
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('bind/unbind identity anonymous', function (t) {
|
||||
const server = ldap.createServer({
|
||||
connectionRouter: function (c) {
|
||||
server.newConnection(c)
|
||||
server.emit('testconnection', c)
|
||||
}
|
||||
})
|
||||
|
||||
server.unbind(function (req, res, next) {
|
||||
t.ok(true, 'server unbind successful')
|
||||
res.end()
|
||||
return next()
|
||||
})
|
||||
|
||||
server.bind('', function (req, res, next) {
|
||||
t.ok(true, 'server bind successful')
|
||||
res.end()
|
||||
return next()
|
||||
})
|
||||
|
||||
const anonDN = ldap.parseDN('cn=anonymous')
|
||||
|
||||
server.listen(t.context.sock, function () {
|
||||
t.ok(true, 'server startup')
|
||||
|
||||
const client = ldap.createClient({ socketPath: t.context.sock })
|
||||
server.once('testconnection', (c) => {
|
||||
t.ok(anonDN.equals(c.ldap.bindDN), 'pre bind dn is correct')
|
||||
client.bind('', '', function (err) {
|
||||
t.error(err, 'client anon bind error')
|
||||
t.ok(anonDN.equals(c.ldap.bindDN), 'anon bind dn is correct')
|
||||
client.unbind(function (err) {
|
||||
t.error(err, 'client anon unbind error')
|
||||
t.ok(anonDN.equals(c.ldap.bindDN), 'anon unbind dn is correct')
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('does not crash on empty DN values', function (t) {
|
||||
const server = ldap.createServer({
|
||||
connectionRouter: function (c) {
|
||||
server.newConnection(c)
|
||||
server.emit('testconnection', c)
|
||||
}
|
||||
})
|
||||
|
||||
server.listen(t.context.sock, function () {
|
||||
const client = ldap.createClient({ socketPath: t.context.sock })
|
||||
server.once('testconnection', () => {
|
||||
client.bind('', 'pw', function (err) {
|
||||
t.ok(err, 'blank bind dn throws error')
|
||||
client.unbind(function () {
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('bind/unbind identity user', function (t) {
|
||||
const server = ldap.createServer({
|
||||
connectionRouter: function (c) {
|
||||
server.newConnection(c)
|
||||
server.emit('testconnection', c)
|
||||
}
|
||||
})
|
||||
|
||||
server.unbind(function (req, res, next) {
|
||||
t.ok(true, 'server unbind successful')
|
||||
res.end()
|
||||
return next()
|
||||
})
|
||||
|
||||
server.bind('', function (req, res, next) {
|
||||
t.ok(true, 'server bind successful')
|
||||
res.end()
|
||||
return next()
|
||||
})
|
||||
|
||||
const anonDN = ldap.parseDN('cn=anonymous')
|
||||
const testDN = ldap.parseDN('cn=anotheruser')
|
||||
|
||||
server.listen(t.context.sock, function () {
|
||||
t.ok(true, 'server startup')
|
||||
|
||||
const client = ldap.createClient({ socketPath: t.context.sock })
|
||||
server.once('testconnection', (c) => {
|
||||
t.ok(anonDN.equals(c.ldap.bindDN), 'pre bind dn is correct')
|
||||
client.bind(testDN.toString(), 'somesecret', function (err) {
|
||||
t.error(err, 'user bind error')
|
||||
t.ok(testDN.equals(c.ldap.bindDN), 'user bind dn is correct')
|
||||
// check rebinds too
|
||||
client.bind('', '', function (err) {
|
||||
t.error(err, 'client anon bind error')
|
||||
t.ok(anonDN.equals(c.ldap.bindDN), 'anon bind dn is correct')
|
||||
// user rebind
|
||||
client.bind(testDN.toString(), 'somesecret', function (err) {
|
||||
t.error(err, 'user bind error')
|
||||
t.ok(testDN.equals(c.ldap.bindDN), 'user rebind dn is correct')
|
||||
client.unbind(function (err) {
|
||||
t.error(err, 'user unbind error')
|
||||
t.ok(anonDN.equals(c.ldap.bindDN), 'user unbind dn is correct')
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('strict routing', function (t) {
|
||||
const testDN = 'cn=valid'
|
||||
let clt
|
||||
let server
|
||||
const sock = t.context.sock
|
||||
vasync.pipeline({
|
||||
funcs: [
|
||||
function setup (_, cb) {
|
||||
server = ldap.createServer({})
|
||||
// invalid DNs would go to default handler
|
||||
server.search('', function (req, res, next) {
|
||||
t.ok(req.dn)
|
||||
t.equal(typeof (req.dn), 'object')
|
||||
t.equal(req.dn.toString(), testDN)
|
||||
res.end()
|
||||
next()
|
||||
})
|
||||
server.listen(sock, function () {
|
||||
t.ok(true, 'server startup')
|
||||
clt = ldap.createClient({
|
||||
socketPath: sock
|
||||
})
|
||||
cb()
|
||||
})
|
||||
},
|
||||
function testGood (_, cb) {
|
||||
clt.search(testDN, { scope: 'base' }, function (err, res) {
|
||||
t.error(err)
|
||||
res.once('error', function (err2) {
|
||||
t.error(err2)
|
||||
cb(err2)
|
||||
})
|
||||
res.once('end', function (result) {
|
||||
t.ok(result, 'accepted invalid dn')
|
||||
cb()
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
}, function (err) {
|
||||
t.error(err)
|
||||
if (clt) {
|
||||
clt.destroy()
|
||||
}
|
||||
server.close(() => t.end())
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('close accept a callback', function (t) {
|
||||
const server = ldap.createServer()
|
||||
// callback is called when the server is closed
|
||||
server.listen(0, function (err) {
|
||||
t.error(err)
|
||||
server.close(function (err) {
|
||||
t.error(err)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('close without error calls callback', function (t) {
|
||||
const server = ldap.createServer()
|
||||
// when the server is closed without error, the callback parameter is undefined
|
||||
server.listen(1389, '127.0.0.1', function (err) {
|
||||
t.error(err)
|
||||
server.close(function (err) {
|
||||
t.error(err)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('close passes error to callback', function (t) {
|
||||
const server = ldap.createServer()
|
||||
// when the server is closed with an error, the error is the first parameter of the callback
|
||||
server.close(function (err) {
|
||||
t.ok(err)
|
||||
t.end()
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('multithreading support via external server', function (t) {
|
||||
const serverOptions = { }
|
||||
const server = ldap.createServer(serverOptions)
|
||||
const fauxServer = net.createServer(serverOptions, (connection) => {
|
||||
server.newConnection(connection)
|
||||
})
|
||||
fauxServer.log = serverOptions.log
|
||||
fauxServer.ldap = {
|
||||
config: serverOptions
|
||||
}
|
||||
t.ok(server)
|
||||
fauxServer.listen(5555, '127.0.0.1', function () {
|
||||
t.ok(true, 'server listening on ' + server.url)
|
||||
|
||||
t.ok(fauxServer)
|
||||
const client = ldap.createClient({ url: 'ldap://127.0.0.1:5555' })
|
||||
client.on('connect', function () {
|
||||
t.ok(client)
|
||||
client.unbind()
|
||||
fauxServer.close(() => t.end())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('multithreading support via hook', function (t) {
|
||||
const serverOptions = {
|
||||
connectionRouter: (connection) => {
|
||||
server.newConnection(connection)
|
||||
}
|
||||
}
|
||||
const server = ldap.createServer(serverOptions)
|
||||
const fauxServer = ldap.createServer(serverOptions)
|
||||
t.ok(server)
|
||||
fauxServer.listen(0, '127.0.0.1', function () {
|
||||
t.ok(true, 'server listening on ' + server.url)
|
||||
|
||||
t.ok(fauxServer)
|
||||
const client = ldap.createClient({ url: fauxServer.url })
|
||||
client.on('connect', function () {
|
||||
t.ok(client)
|
||||
client.unbind()
|
||||
fauxServer.close(() => t.end())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
tap.test('cross-realm type checks', function (t) {
|
||||
const server = ldap.createServer()
|
||||
const ctx = vm.createContext({})
|
||||
vm.runInContext(
|
||||
'globalThis.search=function(){};\n' +
|
||||
'globalThis.searches=[function(){}];'
|
||||
, ctx)
|
||||
server.search('', ctx.search)
|
||||
server.search('', ctx.searches)
|
||||
t.ok(server)
|
||||
t.end()
|
||||
})
|
||||
58
node_modules/ldapjs/test/url.test.js
generated
vendored
Normal file
58
node_modules/ldapjs/test/url.test.js
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('tap')
|
||||
const { parseURL } = require('../lib')
|
||||
|
||||
test('parse empty', function (t) {
|
||||
const u = parseURL('ldap:///')
|
||||
t.equal(u.hostname, 'localhost')
|
||||
t.equal(u.port, 389)
|
||||
t.ok(!u.DN)
|
||||
t.ok(!u.attributes)
|
||||
t.equal(u.secure, false)
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('parse hostname', function (t) {
|
||||
const u = parseURL('ldap://example.com/')
|
||||
t.equal(u.hostname, 'example.com')
|
||||
t.equal(u.port, 389)
|
||||
t.ok(!u.DN)
|
||||
t.ok(!u.attributes)
|
||||
t.equal(u.secure, false)
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('parse host and port', function (t) {
|
||||
const u = parseURL('ldap://example.com:1389/')
|
||||
t.equal(u.hostname, 'example.com')
|
||||
t.equal(u.port, 1389)
|
||||
t.ok(!u.DN)
|
||||
t.ok(!u.attributes)
|
||||
t.equal(u.secure, false)
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('parse full', function (t) {
|
||||
const u = parseURL('ldaps://ldap.example.com:1389/dc=example%20,dc=com' +
|
||||
'?cn,sn?sub?(cn=Babs%20Jensen)')
|
||||
|
||||
t.equal(u.secure, true)
|
||||
t.equal(u.hostname, 'ldap.example.com')
|
||||
t.equal(u.port, 1389)
|
||||
t.equal(u.DN, 'dc=example ,dc=com')
|
||||
t.ok(u.attributes)
|
||||
t.equal(u.attributes.length, 2)
|
||||
t.equal(u.attributes[0], 'cn')
|
||||
t.equal(u.attributes[1], 'sn')
|
||||
t.equal(u.scope, 'sub')
|
||||
t.equal(u.filter.toString(), '(cn=Babs Jensen)')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('supports href', function (t) {
|
||||
const u = parseURL('ldaps://ldap.example.com:1389/dc=example%20,dc=com?cn,sn?sub?(cn=Babs%20Jensen)')
|
||||
t.equal(u.href, 'ldaps://ldap.example.com:1389/dc=example%20,dc=com?cn,sn?sub?(cn=Babs%20Jensen)')
|
||||
t.end()
|
||||
})
|
||||
22
node_modules/ldapjs/test/utils.js
generated
vendored
Normal file
22
node_modules/ldapjs/test/utils.js
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
'use strict'
|
||||
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
const crypto = require('crypto')
|
||||
|
||||
function uuid () {
|
||||
return crypto.randomBytes(16).toString('hex')
|
||||
}
|
||||
|
||||
function getSock () {
|
||||
if (process.platform === 'win32') {
|
||||
return '\\\\.\\pipe\\' + uuid()
|
||||
} else {
|
||||
return path.join(os.tmpdir(), uuid())
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSock,
|
||||
uuid
|
||||
}
|
||||
Reference in New Issue
Block a user