archive the v1.0 - old db structure

This commit is contained in:
lion
2022-06-16 16:25:31 +08:00
parent bfd70f95dd
commit 1e2544cc57
150 changed files with 0 additions and 706936 deletions
-2
View File
@@ -1,2 +0,0 @@
node_modules/
data/
-4
View File
@@ -1,4 +0,0 @@
{
"singleQuote": true,
"tabWidth": 4
}
-103
View File
@@ -1,103 +0,0 @@
# nodejs 客户端
官方维护的 ip2region, 每次数据更新后会更新到 npm
## Install
**node 版本 : >= 6.0.0**
```
npm install node-ip2region --save
```
## 已测试通过的 node 版本列表
```
6.0.0
6.11.2
8.0.0
10.0.0
12.0.0
```
## Example
```
const searcher = require('node-ip2region').create();
searcher.btreeSearchSync('xxx.xxx.xxx.xxx')
// => { city: 2163, region: '中国|0|广东省|深圳市|联通' }
```
## 实现情况:
现已实现同步和异步查询,具体使用方法可以参考 `nodejs\tests\constructorTest.spec.js``nodejs\tests\createTest.spec.js`
## 如何贡献?
你可以任意修改代码,但必须确保通过全部的单元测试。要保证通过全部的单元测试,请在 Nodejs 控制台下切换到 nodejs 目录:
1)在此之前,请先运行 `npm i` 确保你已经安装了各类初始化第三方工具。
2)然后运行 `npm run coverage` 确保你的代码可以通过全部测试(必要时可以添加测试)。
```bash
D:\Projects\ip2region\binding\nodejs>npm run coverage
> ip2region@0.0.1 coverage D:\Projects\ip2region\binding\nodejs
> npm run test && jest --coverage
> ip2region@0.0.1 test D:\Projects\ip2region\binding\nodejs
> jest
PASS tests\constructorTest.spec.js
PASS tests\createTest.spec.js
PASS tests\exceptionTest.spec.js
Snapshot Summary
168 snapshots written in 2 test suites.
Test Suites: 3 passed, 3 total
Tests: 14 passed, 14 total
Snapshots: 168 added, 168 total
Time: 1.645s
Ran all test suites.
PASS tests\constructorTest.spec.js
PASS tests\createTest.spec.js
PASS tests\exceptionTest.spec.js
----------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------------|----------|----------|----------|----------|-------------------|
All files | 92.34 | 80.77 | 96 | 93.83 | |
nodejs | 91.95 | 80.26 | 95.65 | 93.51 | |
ip2region.js | 91.95 | 80.26 | 95.65 | 93.51 |... 09,410,460,484 |
nodejs/tests/utils | 100 | 100 | 100 | 100 | |
asyncFor.js | 100 | 100 | 100 | 100 | |
fetchMainVersion.js | 100 | 100 | 100 | 100 | |
testData.js | 100 | 100 | 100 | 100 | |
----------------------|----------|----------|----------|----------|-------------------|
Test Suites: 3 passed, 3 total
Tests: 14 passed, 14 total
Snapshots: 168 passed, 168 total
Time: 1.792s
Ran all test suites.
```
3)使用benchmark测试,结果如下:
```bash
D:\Projects\ip2region\binding\nodejs>node D:\Projects\ip2region\binding\nodejs\tests\benchmarkTests\main.js
MemorySearchSync x 55,969 ops/sec ±2.22% (90 runs sampled)
BinarySearchSync x 610 ops/sec ±5.41% (77 runs sampled)
BtreeSearchSync x 2,439 ops/sec ±6.93% (69 runs sampled)
MemorySearch x 2,924 ops/sec ±0.67% (85 runs sampled)
BinarySearch x 154 ops/sec ±2.20% (69 runs sampled)
BtreeSearch x 294 ops/sec ±2.58% (76 runs sampled)
Rand Name Time (in milliseconds)
1 MemorySearchSync 0.018
2 MemorySearch 0.342
3 BtreeSearchSync 0.410
4 BinarySearchSync 1.639
5 BtreeSearch 3.407
6 BinarySearch 6.497
```
-11
View File
@@ -1,11 +0,0 @@
#!/bin/sh
echo 'create dir'
if [ ! -d "data" ]; then
mkdir data
fi
echo "copy db"
cp '../../data/ip2region.db' './data/'
echo "npm publish"
npm publish
-634
View File
@@ -1,634 +0,0 @@
/**
* ip2region client for nodejs
*
* project: https://github.com/lionsoul2014/ip2region
*
* @author dongyado<dongyado@gmail.com>
* @author leeching<leeching.fx@gmail.com>
* @author dongwei<maledong_github@outlook.com>
*/
const fs = require('fs');
const path = require('path');
const DEFAULT_DB_PATH = path.join(__dirname,'./data/ip2region.db') ;
//#region Private Functions
/**
* Convert ip to long (xxx.xxx.xxx.xxx to a integer)
*
* @param {string} ip
* @return {number} long value
*/
function _ip2long(ip) {
const arr = ip.split('.');
if (arr.length !== 4) {
throw new Error('invalid ip');
}
return arr.reduce((val, n, i) => {
n = Number(n);
if (!Number.isInteger(n) || n < 0 || n > 255) {
throw new Error('invalid ip');
}
return val + IP_BASE[i] * n;
}, 0);
}
/**
* Get long value from buffer with specified offset
*
* @param {Buffer} buffer
* @param {number} offset
* @return {number} long value
*/
function _getLong(buffer, offset) {
const val =
(buffer[offset] & 0x000000ff) |
((buffer[offset + 1] << 8) & 0x0000ff00) |
((buffer[offset + 2] << 16) & 0x00ff0000) |
((buffer[offset + 3] << 24) & 0xff000000);
return val < 0 ? val >>> 0 : val;
}
//#endregion
//#region Private Variables
// We don't wanna expose a private global settings to
// the public for safety reason.
const _globalInstances = new Map();
const IP_BASE = [16777216, 65536, 256, 1];
const INDEX_BLOCK_LENGTH = 12;
const TOTAL_HEADER_LENGTH = 8192;
// Private Message Symbols for functions
const PrepareHeader = Symbol('#PrepareHeader');
const CalTotalBlocks = Symbol('#CalsTotalBlocks');
const ReadDataSync = Symbol('#ReadDataSync');
const ReadData = Symbol('#ReadData');
//#endregion
class IP2Region {
//#region Private Functions
[CalTotalBlocks]() {
const superBlock = Buffer.alloc(8);
fs.readSync(this.dbFd, superBlock, 0, 8, 0);
this.firstIndexPtr = _getLong(superBlock, 0);
this.lastIndexPtr = _getLong(superBlock, 4);
this.totalBlocks =
(this.lastIndexPtr - this.firstIndexPtr) / INDEX_BLOCK_LENGTH + 1;
}
[PrepareHeader]() {
fs.readSync(
this.dbFd,
this.headerIndexBuffer,
0,
TOTAL_HEADER_LENGTH,
8
);
for (let i = 0; i < TOTAL_HEADER_LENGTH; i += 8) {
const startIp = _getLong(this.headerIndexBuffer, i);
const dataPtr = _getLong(this.headerIndexBuffer, i + 4);
if (dataPtr == 0) break;
this.headerSip.push(startIp);
this.headerPtr.push(dataPtr);
this.headerLen++; // header index size count
}
}
[ReadData](dataPos, callBack) {
if (dataPos == 0) return callBack(null, null);
const dataLen = (dataPos >> 24) & 0xff;
dataPos = dataPos & 0x00ffffff;
const dataBuffer = Buffer.alloc(dataLen);
fs.read(this.dbFd, dataBuffer, 0, dataLen, dataPos, (err, result) => {
if (err) {
callBack(err, null);
}
else {
const city = _getLong(dataBuffer, 0);
const region = dataBuffer.toString('utf8', 4, dataLen);
callBack(null, { city, region });
}
});
}
[ReadDataSync](dataPos) {
if (dataPos == 0) return null;
const dataLen = (dataPos >> 24) & 0xff;
dataPos = dataPos & 0x00ffffff;
const dataBuffer = Buffer.alloc(dataLen);
fs.readSync(this.dbFd, dataBuffer, 0, dataLen, dataPos);
const city = _getLong(dataBuffer, 0);
const region = dataBuffer.toString('utf8', 4, dataLen);
return { city, region };
}
//#endregion
//#region Static Functions
// Single Instance
static create(dbPath = DEFAULT_DB_PATH) {
let existInstance = _globalInstances.get(dbPath);
if (existInstance == null) {
existInstance = new IP2Region({ dbPath: dbPath });
}
return existInstance;
}
/**
* For backward compatibility
*/
static destroy() {
_globalInstances.forEach(([key, instance]) => {
instance.destroy();
});
}
//#endregion
constructor(options = {}) {
const { dbPath } = options;
// Keep for MemorySearch
this.totalInMemoryBytesSize = fs.statSync(dbPath).size;
this.totalInMemoryBytes = null;
this.dbFd = fs.openSync(dbPath, 'r');
this.dbPath = dbPath;
_globalInstances.set(this.dbPath, this);
this.totalBlocks = this.firstIndexPtr = this.lastIndexPtr = 0;
this[CalTotalBlocks]();
this.headerIndexBuffer = Buffer.alloc(TOTAL_HEADER_LENGTH);
this.headerSip = [];
this.headerPtr = [];
this.headerLen = 0;
this[PrepareHeader]();
}
//#region Public Functions
/**
* Destroy the current file by closing it.
*/
destroy() {
fs.closeSync(this.dbFd);
_globalInstances.delete(this.dbPath);
}
/**
* Sync of binarySearch.
* @param {string} ip The IP address to search for.
* @return {SearchResult} A result something like `{ city: 2163, region: '中国|0|广东省|深圳市|阿里云' }`
*/
binarySearchSync(ip) {
ip = _ip2long(ip);
let low = 0;
let mid = 0;
let high = this.totalBlocks;
let pos = 0;
let sip = 0;
const indexBuffer = Buffer.alloc(12);
// binary search
while (low <= high) {
mid = (low + high) >> 1;
pos = this.firstIndexPtr + mid * INDEX_BLOCK_LENGTH;
fs.readSync(this.dbFd, indexBuffer, 0, INDEX_BLOCK_LENGTH, pos);
sip = _getLong(indexBuffer, 0);
if (ip < sip) {
high = mid - 1;
} else {
sip = _getLong(indexBuffer, 4);
if (ip > sip) {
low = mid + 1;
} else {
sip = _getLong(indexBuffer, 8);
break;
}
}
}
return this[ReadDataSync](sip);
}
/**
* Async of binarySearch.
* @param {string} ip The IP address to search for.
* @param {Function} callBack The callBack function with two parameters, if successful,
* err is null and result is `{ city: 2163, region: '中国|0|广东省|深圳市|阿里云' }`
*/
binarySearch(ip, callBack) {
ip = _ip2long(ip);
let low = 0;
let mid = 0;
let high = this.totalBlocks;
let pos = 0;
let sip = 0;
const indexBuffer = Buffer.alloc(12);
const _self = this;
// Because `while` is a sync method, we have to convert this to a recursive loop
// and in each loop we should continue calling `setImmediate` until we found the IP.
function _innerAsyncWhile() {
if (low <= high) {
mid = (low + high) >> 1;
pos = _self.firstIndexPtr + mid * INDEX_BLOCK_LENGTH;
// Now async read the file
fs.read(_self.dbFd, indexBuffer, 0, INDEX_BLOCK_LENGTH, pos, (err) => {
if (err) {
return callBack(err, null);
}
sip = _getLong(indexBuffer, 0);
if (ip < sip) {
high = mid - 1;
setImmediate(_innerAsyncWhile);
} else {
sip = _getLong(indexBuffer, 4);
if (ip > sip) {
low = mid + 1;
setImmediate(_innerAsyncWhile);
} else {
sip = _getLong(indexBuffer, 8);
_self[ReadData](sip, (err, result) => {
callBack(err, result);
});
}
}
});
}
}
// Call this immediately
_innerAsyncWhile();
}
/**
* Sync of btreeSearch.
* @param {string} ip The IP address to search for.
* @return {Function} A result something like `{ city: 2163, region: '中国|0|广东省|深圳市|阿里云' }`
*/
btreeSearchSync(ip) {
ip = _ip2long(ip);
// first search (in header index)
let low = 0;
let mid = 0;
let high = this.headerLen;
let sptr = 0;
let eptr = 0;
while (low <= high) {
mid = (low + high) >> 1;
if (ip == this.headerSip[mid]) {
if (mid > 0) {
sptr = this.headerPtr[mid - 1];
eptr = this.headerPtr[mid];
} else {
sptr = this.headerPtr[mid];
eptr = this.headerPtr[mid + 1];
}
break;
}
if (ip < this.headerSip[mid]) {
if (mid == 0) {
sptr = this.headerPtr[mid];
eptr = this.headerPtr[mid + 1];
break;
} else if (ip > this.headerSip[mid - 1]) {
sptr = this.headerPtr[mid - 1];
eptr = this.headerPtr[mid];
break;
}
high = mid - 1;
} else {
if (mid == this.headerLen - 1) {
sptr = this.headerPtr[mid - 1];
eptr = this.headerPtr[mid];
break;
} else if (ip <= this.headerSip[mid + 1]) {
sptr = this.headerPtr[mid];
eptr = this.headerPtr[mid + 1];
break;
}
low = mid + 1;
}
}
// match nothing
if (sptr == 0) return null;
// second search (in index)
const blockLen = eptr - sptr;
const blockBuffer = Buffer.alloc(blockLen + INDEX_BLOCK_LENGTH);
fs.readSync(
this.dbFd,
blockBuffer,
0,
blockLen + INDEX_BLOCK_LENGTH,
sptr
);
low = 0;
high = blockLen / INDEX_BLOCK_LENGTH;
let p = 0;
let sip = 0;
while (low <= high) {
mid = (low + high) >> 1;
p = mid * INDEX_BLOCK_LENGTH;
sip = _getLong(blockBuffer, p);
if (ip < sip) {
high = mid - 1;
} else {
sip = _getLong(blockBuffer, p + 4);
if (ip > sip) {
low = mid + 1;
} else {
sip = _getLong(blockBuffer, p + 8);
break;
}
}
}
return this[ReadDataSync](sip);
}
/**
* Async of btreeSearch.
* @param {string} ip The IP address to search for.
* @param {Function} callBack The callBack function with two parameters, if successful,
* err is null and result is `{ city: 2163, region: '中国|0|广东省|深圳市|阿里云' }`
*/
btreeSearch(ip, callBack) {
ip = _ip2long(ip);
// first search (in header index)
let low = 0;
let mid = 0;
let high = this.headerLen;
let sptr = 0;
let eptr = 0;
while (low <= high) {
mid = (low + high) >> 1;
if (ip == this.headerSip[mid]) {
if (mid > 0) {
sptr = this.headerPtr[mid - 1];
eptr = this.headerPtr[mid];
} else {
sptr = this.headerPtr[mid];
eptr = this.headerPtr[mid + 1];
}
break;
}
if (ip < this.headerSip[mid]) {
if (mid == 0) {
sptr = this.headerPtr[mid];
eptr = this.headerPtr[mid + 1];
break;
} else if (ip > this.headerSip[mid - 1]) {
sptr = this.headerPtr[mid - 1];
eptr = this.headerPtr[mid];
break;
}
high = mid - 1;
} else {
if (mid == this.headerLen - 1) {
sptr = this.headerPtr[mid - 1];
eptr = this.headerPtr[mid];
break;
} else if (ip <= this.headerSip[mid + 1]) {
sptr = this.headerPtr[mid];
eptr = this.headerPtr[mid + 1];
break;
}
low = mid + 1;
}
}
// match nothing
if (sptr == 0) return callBack(null, null);
let p = 0;
let sip = 0;
// second search (in index)
const blockLen = eptr - sptr;
const blockBuffer = Buffer.alloc(blockLen + INDEX_BLOCK_LENGTH);
low = 0;
high = blockLen / INDEX_BLOCK_LENGTH;
const _self = this;
function _innerAsyncWhile() {
if (low <= high) {
mid = (low + high) >> 1;
p = mid * INDEX_BLOCK_LENGTH;
// Use this to call the method itself as
// an asynchronize step
fs.read(_self.dbFd, blockBuffer,
0,
blockLen + INDEX_BLOCK_LENGTH,
sptr, (err) => {
if (err) {
return callBack(err, null);
}
sip = _getLong(blockBuffer, p);
if (ip < sip) {
high = mid - 1;
setImmediate(_innerAsyncWhile);
} else {
sip = _getLong(blockBuffer, p + 4);
if (ip > sip) {
low = mid + 1;
setImmediate(_innerAsyncWhile);
} else {
sip = _getLong(blockBuffer, p + 8);
_self[ReadData](sip, (err, result) => {
callBack(err, result);
});
}
}
});
}
else {
// If we found nothing, return null
return callBack(null, null);
}
}
_innerAsyncWhile();
}
/**
* Sync of MemorySearch.
* @param {String} ip
*/
memorySearchSync(ip) {
ip = _ip2long(ip);
if (this.totalInMemoryBytes === null) {
this.totalInMemoryBytes = Buffer.alloc(this.totalInMemoryBytesSize);
fs.readSync(this.dbFd, this.totalInMemoryBytes, 0, this.totalInMemoryBytesSize, 0);
this.firstIndexPtr = _getLong(this.totalInMemoryBytes, 0);
this.lastIndexPtr = _getLong(this.totalInMemoryBytes, 4);
this.totalBlocks = ((this.lastIndexPtr - this.firstIndexPtr) / INDEX_BLOCK_LENGTH) | 0 + 1;
}
let l = 0, h = this.totalBlocks;
let sip = 0;
let m = 0, p = 0;
while (l <= h) {
m = (l + h) >> 1;
p = (this.firstIndexPtr + m * INDEX_BLOCK_LENGTH) | 0;
sip = _getLong(this.totalInMemoryBytes, p);
if (ip < sip) {
h = m - 1;
}
else {
sip = _getLong(this.totalInMemoryBytes, p + 4);
if (ip > sip) {
l = m + 1;
}
else {
sip = _getLong(this.totalInMemoryBytes, p + 8);
//not matched
if (sip === 0) return null;
//get the data
let dataLen = ((sip >> 24) & 0xFF) | 0;
let dataPtr = ((sip & 0x00FFFFFF)) | 0;
let city = _getLong(this.totalInMemoryBytes, dataPtr);
const bufArray = new Array();
for (let startPos = dataPtr + 4, i = startPos; i < startPos + dataLen - 4; ++i) {
bufArray.push(this.totalInMemoryBytes[i]);
}
const region = Buffer.from(bufArray, 0).toString();
return { city, region };
}
}
}
}
/**
* Async of MemorySearch.
* @param {String} ip
*/
memorySearch(ip, callBack) {
let _ip = _ip2long(ip);
let l = 0, h = this.totalBlocks;
let sip = 0;
let m = 0, p = 0;
let self = this;
function _innerMemorySearchLoop() {
if (l <= h) {
m = (l + h) >> 1;
p = (self.firstIndexPtr + m * INDEX_BLOCK_LENGTH) | 0;
sip = _getLong(self.totalInMemoryBytes, p);
if (_ip < sip) {
h = m - 1;
setImmediate(_innerMemorySearchLoop);
}
else {
sip = _getLong(self.totalInMemoryBytes, p + 4);
if (_ip > sip) {
l = m + 1;
setImmediate(_innerMemorySearchLoop);
}
else {
sip = _getLong(self.totalInMemoryBytes, p + 8);
//not matched
if (sip === 0) return callBack(null, null);
//get the data
let dataLen = ((sip >> 24) & 0xFF) | 0;
let dataPtr = ((sip & 0x00FFFFFF)) | 0;
let city = _getLong(self.totalInMemoryBytes, dataPtr);
const bufArray = new Array();
for (let startPos = dataPtr + 4, i = startPos; i < startPos + dataLen - 4; ++i) {
bufArray.push(self.totalInMemoryBytes[i]);
}
const region = Buffer.from(bufArray).toString();
callBack(null, { city, region });
}
}
}
else {
callBack(null, null);
}
}
if (this.totalInMemoryBytes === null) {
this.totalInMemoryBytes = Buffer.alloc(this.totalInMemoryBytesSize);
fs.read(this.dbFd, this.totalInMemoryBytes, 0, this.totalInMemoryBytesSize, 0, (err) => {
if (err) {
callBack(err, null);
}
else {
this.firstIndexPtr = _getLong(this.totalInMemoryBytes, 0);
this.lastIndexPtr = _getLong(this.totalInMemoryBytes, 4);
this.totalBlocks = ((this.lastIndexPtr - this.firstIndexPtr) / INDEX_BLOCK_LENGTH) | 0 + 1;
_innerMemorySearchLoop();
}
});
}
else {
_innerMemorySearchLoop();
}
}
}
//#endregion
module.exports = IP2Region;
-3930
View File
File diff suppressed because it is too large Load Diff
-33
View File
@@ -1,33 +0,0 @@
{
"name": "node-ip2region",
"version": "1.0.2",
"description": "official nodejs client of ip2region",
"main": "ip2region.js",
"scripts": {
"test": "jest",
"coverage": "npm run test && jest --coverage"
},
"files": ["data/"],
"repository": {
"type": "git",
"url": "https://github.com/lionsoul2014/ip2region"
},
"keywords": [
"ip2region",
"ip",
"region"
],
"author": "dongyado",
"license": "ISC",
"bugs": {
"url": "https://github.com/lionsoul2014/ip2region/issues"
},
"homepage": "https://github.com/lionsoul2014/ip2region",
"devDependencies": {
"jest": "^19.0.2",
"benchmark": "^2.1.4"
},
"engines": {
"node" : ">=6.0.0"
}
}
@@ -1,94 +0,0 @@
const Benchmark = require('benchmark');
const suite = new Benchmark.Suite();
const searcher = require('../../ip2region').create('../../data/ip2region.db');
const testDatas = require('../utils/testData');
const asyncFor = require('../utils/asyncFor');
suite.add("MemorySearchSync", () => {
for (let i = 0; i < testDatas.length; ++i) {
searcher.memorySearchSync(testDatas[i]);
}
})
.add("BinarySearchSync", () => {
for (let i = 0; i < testDatas.length; ++i) {
searcher.binarySearchSync(testDatas[i]);
}
})
.add("BtreeSearchSync", () => {
for (let i = 0; i < testDatas.length; ++i) {
searcher.btreeSearchSync(testDatas[i]);
}
})
.add("MemorySearch", {
defer: true,
fn: function (completeCallBack) {
asyncFor(testDatas,
(v, c) => {
searcher.memorySearch(v, () => {
c();
});
},
() => {
completeCallBack.resolve();
});
}
})
.add("BinarySearch", {
defer: true,
fn: function (completeCallBack) {
asyncFor(testDatas,
(v, c) => {
searcher.binarySearch(v, () => {
c();
});
},
() => {
completeCallBack.resolve();
});
}
})
.add("BtreeSearch", {
defer: true,
fn: function (completeCallBack) {
asyncFor(testDatas,
(v, c) => {
searcher.btreeSearch(v, () => {
c();
});
},
() => {
completeCallBack.resolve();
});
}
})
.on('cycle', function (event) {
console.log(String(event.target));
})
.on('complete', function () {
let results = new Array();
for (let prop in this) {
if (!isNaN(prop)) {
const eachResult = {
name: this[prop].name,
mean: this[prop].stats.mean * 1000, //second => millisecond
moe: this[prop].stats.moe,
rme: this[prop].stats.rme,
sem: this[prop].stats.sem
}
results.push(eachResult);
}
}
results = results.sort((a, b) => { return a.mean - b.mean });
console.log(`Rand\t${'Name'.padEnd(20)}Time (in milliseconds)`);
let id = 1;
for (let r of results) {
console.log(`${id++}\t${r.name.padEnd(20)}${r.mean.toFixed(3)}`);
}
})
.run({ async: true });
@@ -1,145 +0,0 @@
// This test is used for tesing of a static function `create` of IP2Region
const IP2Region = require('../../ip2region');
const testIps = require('../utils/testData');
const asyncFor = require('../utils/asyncFor');
describe('Constructor Test', () => {
let instance;
beforeAll(() => {
instance = new IP2Region({ dbPath: '../../data/ip2region.db' });
});
afterAll(() => {
IP2Region.destroy();
});
test('btreeSearchSync query', () => {
for (const ip of testIps) {
expect(instance.btreeSearchSync(ip)).toMatchSnapshot();
}
});
test('binarySearchSync query', () => {
for (const ip of testIps) {
expect(instance.binarySearchSync(ip)).toMatchSnapshot();
}
});
test('memorySearchSync query', () => {
for (const ip of testIps) {
expect(instance.memorySearchSync(ip)).toMatchSnapshot();
}
});
//#region callBack
test('binarySearch query', (done) => {
asyncFor(testIps,
(value, continueCallBack) => {
instance.binarySearch(value, (err, result) => {
expect(err).toBe(null);
expect(result).toMatchSnapshot();
continueCallBack();
});
},
() => { done() });
});
test('btreeSearch query', (done) => {
asyncFor(testIps,
(value, continueCallBack) => {
instance.btreeSearch(value, (err, result) => {
expect(err).toBe(null);
expect(result).toMatchSnapshot();
continueCallBack();
});
},
() => { done() });
});
test('memorySearch query', (done) => {
asyncFor(testIps,
(value, continueCallBack) => {
instance.memorySearch(value, (err, result) => {
expect(err).toBe(null);
expect(result).toMatchSnapshot();
continueCallBack();
});
},
() => { done() });
});
//#endregion
//#region Async Promisify test
const node_ver = require('../utils/fetchMainVersion');
// If we have Nodejs >= 8, we now support `async` and `await`
if (node_ver >= 8) {
const asyncBinarySearch = async (ip) => {
return new Promise((resolve, reject) => {
instance.binarySearch(ip, (err, result) => {
if (err) {
reject(err);
}
else {
resolve(result);
}
});
});
};
const asyncBtreeSearch = async (ip) => {
return new Promise((resolve, reject) => {
instance.btreeSearch(ip, (err, result) => {
if (err) {
reject(err);
}
else {
resolve(result);
}
});
});
};
const asyncMemorySearch = async (ip) => {
return new Promise((succ, fail) => {
instance.memorySearch(ip, (err, result) => {
if (err) {
fail(err);
}
else {
succ(result);
}
});
});
}
test('async binarySearch query', async () => {
for (let i = 0; i < testIps.length; ++i) {
const result = await asyncBinarySearch(testIps[i]);
expect(result).toMatchSnapshot();
}
});
test('async btreeSearch query', async () => {
for (let i = 0; i < testIps.length; ++i) {
const result = await asyncBtreeSearch(testIps[i]);
expect(result).toMatchSnapshot();
}
});
test('async memorySearch query', async () => {
for (let i = 0; i < testIps.length; ++i) {
const result = await asyncMemorySearch(testIps[i]);
expect(result).toMatchSnapshot();
}
});
}
//#endregion
});
@@ -1,146 +0,0 @@
// This test is used for tesing of a static function `create` of IP2Region
const IP2Region = require('../../ip2region');
const testIps = require('../utils/testData');
const asyncFor = require('../utils/asyncFor');
describe('Create Test', () => {
let instance;
beforeAll(() => {
instance = IP2Region.create('../../data/ip2region.db');
});
afterAll(() => {
IP2Region.destroy();
});
test('btreeSearchSync query', () => {
for (const ip of testIps) {
expect(instance.btreeSearchSync(ip)).toMatchSnapshot();
}
});
test('binarySearchSync query', () => {
for (const ip of testIps) {
expect(instance.binarySearchSync(ip)).toMatchSnapshot();
}
});
test('memorySearchSync query', () => {
for (const ip of testIps) {
expect(instance.memorySearchSync(ip)).toMatchSnapshot();
}
});
//#region callBack
test('binarySearch query', (done) => {
asyncFor(testIps,
(value, continueCallBack) => {
instance.binarySearch(value, (err, result) => {
expect(err).toBe(null);
expect(result).toMatchSnapshot();
continueCallBack();
});
},
() => { done() });
});
test('btreeSearch query', (done) => {
asyncFor(testIps,
(value, continueCallBack) => {
instance.btreeSearch(value, (err, result) => {
expect(err).toBe(null);
expect(result).toMatchSnapshot();
continueCallBack();
});
},
() => { done() });
});
test('memorySearch query', (done) => {
asyncFor(testIps,
(value, continueCallBack) => {
instance.memorySearch(value, (err, result) => {
expect(err).toBe(null);
expect(result).toMatchSnapshot();
continueCallBack();
});
},
() => { done() });
});
//#endregion
//#region Async Promisify test
const node_ver = require('../utils/fetchMainVersion');
// If we have Nodejs >= 8, we now support `async` and `await`
if (node_ver >= 8) {
const asyncBinarySearch = async (ip) => {
return new Promise((resolve, reject) => {
instance.binarySearch(ip, (err, result) => {
if (err) {
reject(err);
}
else {
resolve(result);
}
});
});
};
const asyncBtreeSearch = async (ip) => {
return new Promise((resolve, reject) => {
instance.btreeSearch(ip, (err, result) => {
if (err) {
reject(err);
}
else {
resolve(result);
}
});
});
};
const asyncMemorySearch = async (ip) => {
return new Promise((succ, fail) => {
instance.memorySearch(ip, (err, result) => {
if (err) {
fail(err);
}
else {
succ(result);
}
});
});
}
test('async binarySearch query', async () => {
for (let i = 0; i < testIps.length; ++i) {
const result = await asyncBinarySearch(testIps[i]);
expect(result).toMatchSnapshot();
}
});
test('async btreeSearch query', async () => {
for (let i = 0; i < testIps.length; ++i) {
const result = await asyncBtreeSearch(testIps[i]);
expect(result).toMatchSnapshot();
}
});
test('async memorySearch query', async () => {
for (let i = 0; i < testIps.length; ++i) {
const result = await asyncMemorySearch(testIps[i]);
expect(result).toMatchSnapshot();
}
});
}
//#endregion
});
@@ -1,28 +0,0 @@
// This test is used for tesing of exceptions
const IP2Region = require('../../ip2region');
describe('Constructor Test', () => {
let instance;
beforeAll(() => {
instance = new IP2Region({ dbPath: '../../data/ip2region.db' })
});
afterAll(() => {
instance.destroy();
});
test('IP invalid test', () => {
const invalidIps = ['255.234.233', '255.255.-1.255', null, undefined, '', 'x.255.y.200'];
for (const ip of invalidIps) {
expect(() => instance.btreeSearchSync(ip)).toThrow();
expect(() => instance.binarySearchSync(ip)).toThrow();
}
});
test('File Not Found test', () => {
expect(() => new IP2Region({ dbPath: 'A Bad File or Path Here' })).toThrow();
});
});
-23
View File
@@ -1,23 +0,0 @@
/**
* Async For
* @param {Array} groupArray
* @param {Function} exeCallBack
* @param {Function} finalCallBack
*/
function asyncFor(groupArray, exeCallBack, finalCallBack) {
let i = 0;
function _innerAsyncLoop() {
if (i < groupArray.length) {
exeCallBack(groupArray[i++], _innerAsyncLoop);
}
else {
finalCallBack();
}
}
_innerAsyncLoop();
}
module.exports = asyncFor;
@@ -1,9 +0,0 @@
let node_ver = process.version
// Because nodejs's version is something like `v8.11.3`. So we should ignore `v` first
node_ver = node_ver.substr(1);
// Splitted by `.`
node_ver = node_ver.split('.');
// Take the main version number
node_ver = parseInt(node_ver[0]);
module.exports = node_ver;
-16
View File
@@ -1,16 +0,0 @@
module.exports = [
'0.0.0.0',
'10.10.10.10',
'210.109.255.230',
'192.168.0.1',
'255.255.255.255',
'77.49.66.88',
'210.248.255.231',
'35.193.251.120',
'197.84.60.202',
'183.196.233.159',
'20.108.91.101',
'120.196.148.137',
'249.255.250.200',
'112.65.1.130'
]
File diff suppressed because it is too large Load Diff