Skip to content

Commit

Permalink
add unit tests for some core functions/configs
Browse files Browse the repository at this point in the history
  • Loading branch information
zhuzhuor committed Jul 3, 2022
1 parent bef3583 commit 0212c9e
Show file tree
Hide file tree
Showing 13 changed files with 385 additions and 62 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ The source code is released under [AGPL v3](http://www.gnu.org/licenses/agpl-3.0

## Credits

Please visit [this page](http://uku.im/contributors) for an updated list of our contributors.
Please visit [this page](http://uku.im/contributors) for an up-to-date list of our contributors.

## Developmeent

Update URL and server configs under the folder `src/configs/`.

Run `npm ci` to install dependencies exactly as they are listed in the package-lock.json file.

Run `npm run test` to create a zip file for uploading and testing.
7 changes: 7 additions & 0 deletions babel.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"env": {
"test": {
"plugins": ["@babel/plugin-transform-modules-commonjs"]
}
}
}
2 changes: 1 addition & 1 deletion e2e_tests/chrome_extention.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
jest.setTimeout(60000); // in milliseconds
jest.setTimeout(90000); // in milliseconds

const EXTENSION_INIT_WAIT_TIME = 3000;
const HEADER_TEST_URL = 'https://httpbin.org/headers';
Expand Down
8 changes: 7 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
module.exports = {
preset: 'jest-puppeteer',
'preset': 'jest-puppeteer',
'testRegex': '(/__tests__/.*|(\\.|/)(test|spec))\\.(mjs?|jsx?|js?|tsx?|ts?)$',
'transform': {
'^.+\\.jsx?$': 'babel-jest',
'^.+\\.mjs$': 'babel-jest',
},
'moduleFileExtensions': ['js', 'jsx', 'mjs'],
};
49 changes: 49 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"test": "npm run clean && node tools/create_zip.js && unzip -q dist/upload_to_chrome_store.zip -d dist/unzipped_chrome_extension && jest --verbose"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.18.6",
"archiver": "^5.3.1",
"eslint": "^8.18.0",
"eslint-config-google": "^0.14.0",
Expand Down
15 changes: 15 additions & 0 deletions src/configs/servers.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {
DEFAULT_PROXY_ADDRESS, BACKUP_PROXY_ADDRESS,
DEFAULT_PROXY_PROTOCOL, BACKUP_PROXY_PROTOCOL} from './servers.mjs';

test('The proxy addresses must not be localhost', () => {
expect(DEFAULT_PROXY_ADDRESS).not.toMatch(/localhost/i);
expect(DEFAULT_PROXY_ADDRESS).not.toMatch(/127\.0\.0\.1/i);
expect(BACKUP_PROXY_ADDRESS).not.toMatch(/localhost/i);
expect(BACKUP_PROXY_ADDRESS).not.toMatch(/127\.0\.0\.1/i);
});

test('Production must use HTTPS proxy', () => {
expect(DEFAULT_PROXY_PROTOCOL).toBe('HTTPS');
expect(BACKUP_PROXY_PROTOCOL).toBe('HTTPS');
});
39 changes: 39 additions & 0 deletions src/configs/urls.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {HEADER_URLS, PROXY_BYPASS_URLS, PROXY_URLS} from './urls.mjs';


test('The proxy URL list must contain some domains', () => {
expect(PROXY_URLS.filter((url) => url.includes('.qq.com'))).not.toHaveLength(0);
expect(PROXY_URLS.filter(
(url) => url.includes('flask-test-iwauxcyxjb.cn-hangzhou.fcapp.run/'))).not.toHaveLength(0);
});

test('Must not contain the all-url rules', () => {
[HEADER_URLS, PROXY_BYPASS_URLS, PROXY_URLS].forEach((urlList) => {
expect(urlList.filter((url) => url.startsWith('http://*/'))).toHaveLength(0);
expect(urlList.filter((url) => url.startsWith('https://*/'))).toHaveLength(0);
});
});

test('All URLs must start with http:// or https://', () => {
const regex = /^(http|https):\/\//i;
[HEADER_URLS, PROXY_BYPASS_URLS, PROXY_URLS].forEach((urlList) => {
expect(urlList.filter((url) => !regex.test(url))).toHaveLength(0);
});
});

test('All https URLs must have path that is * or empty', () => {
/*
* For example:
* - Wrong: https://example.com/abc/*
* - Right: https://example.com/*
* - Right: https://example.com/
*/
[HEADER_URLS, PROXY_BYPASS_URLS, PROXY_URLS].forEach((urlList) => {
for (const url of urlList) {
if (url.startsWith('https://')) {
const domainRemoved = url.slice('https://'.length).split('/')[1];
expect(['*', '']).toContain(domainRemoved);
}
}
});
});
132 changes: 132 additions & 0 deletions src/modules/_url_utils.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import {urls2pac} from './_url_utils.mjs';

// urlWhitelist, urlList,
// proxyProtocol1, proxyAddress1,
// proxyProtocol2, proxyAddress2) {

const TEST_PROXY_PROTOCOL_1 = 'HTTPS';
const TEST_PROXY_ADDRESS_1 = 'proxy.example.com';
const TEST_PROXY_PROTOCOL_2 = 'https';
const TEST_PROXY_ADDRESS_2 = '1.2.3.4';


const TEST_BYPASS_URL_LIST = [
'http://bangumi.bilibili.com/index/ding-count.json',
];

const TEST_URL_LIST = [
'http://*/*',
'https://*/*',
'http://*.video.qq.com/*',
'https://*.video.qq.com/*',
'http://vd.l.qq.com/*',
'https://vd.l.qq.com/*',
'http://example.com',
'https://example.com',
'http://example.com/',
'https://example.com/',
'http://*.example.com/*',
'https://*.example.com/*',
'http://*.example.com/path.json?aaa=bbb',
'https://*.example.com/path.json?aaa=bbb',
'http://*.example.com/path.json?aaa=bbb*',
'https://*.example.com/path.json?aaa=bbb*',
'http://122.72.82.31/*',
];

const EXPECTED_PAC_CONTENT = [
'var _http_map = {',
' \'white\': {',
' \'any\': [],',
' \'bangumi.bilibili.com\': [',
' /^\\/index\\/ding\\-count\\.json$/i',
' ]',
' },',
' \'proxy\': {',
' \'any\': [',
' /^[^/]*\\//i,',
' /^[^/]*\\.video\\.qq\\.com\\//i,',
' /^[^/]*\\.example\\.com\\//i,',
' /^[^/]*\\.example\\.com\\/path\\.json\\?aaa=bbb$/i,',
' /^[^/]*\\.example\\.com\\/path\\.json\\?aaa=bbb/i',
' ],',
' \'vd.l.qq.com\': [',
' /^\\//i',
' ],',
' \'example.com\': [',
' /^\\/$/i,',
' /^\\/$/i',
' ],',
' \'122.72.82.31\': [',
' /^\\//i',
' ]',
' }',
'};',
'var _https_map = {',
' \'white\': {',
' \'any\': []',
' },',
' \'proxy\': {',
' \'any\': [',
' /^[^/]*\\//i,',
' /^[^/]*\\.video\\.qq\\.com\\//i,',
' /^[^/]*\\.example\\.com\\//i,',
' /^[^/]*\\.example\\.com\\/path\\.json\\?aaa=bbb$/i,',
' /^[^/]*\\.example\\.com\\/path\\.json\\?aaa=bbb/i',
' ],',
' \'vd.l.qq.com\': [',
' /^\\//i',
' ],',
' \'example.com\': [',
' /^\\/$/i,',
' /^\\/$/i',
' ]',
' }',
'};',
'var _proxy_str = \'HTTPS proxy.example.com; HTTPS 1.2.3.4; DIRECT;\';',
'',
'function _check_regex_list(regex_list, str) {',
' if (str.slice(0, 4) === \':80/\')',
' str = str.slice(3);',
' for (var i = 0; i < regex_list.length; i++)',
' if (regex_list[i].test(str))',
' return true;',
' return false;',
'}',
'',
'function _check_patterns(patterns, hostname, full_url, prot_len) {',
' if (patterns.hasOwnProperty(hostname))',
' if (_check_regex_list(patterns[hostname],',
' full_url.slice(prot_len + hostname.length)))',
' return true;',
' if (_check_regex_list(patterns.any,',
' full_url.slice(prot_len)))',
' return true;',
' return false;',
'}',
'',
'function _find_proxy(url_map, host, url, prot_len) {',
' if (_check_patterns(url_map.white, host, url, prot_len))',
' return \'DIRECT\';',
' if (_check_patterns(url_map.proxy, host, url, prot_len))',
' return _proxy_str;',
' return \'DIRECT\';',
'}',
'',
'function FindProxyForURL(url, host) {',
' var prot = url.slice(0, 6);',
' if (prot === \'http:/\')',
' return _find_proxy(_http_map, host, url, 7);',
' else if (prot === \'https:\')',
' return _find_proxy(_https_map, host, url, 8);',
' return \'DIRECT\';',
'}',
].join('\n') + '\n';


test('Should produce the expected PAC content', () => {
expect(urls2pac(
TEST_BYPASS_URL_LIST, TEST_URL_LIST,
TEST_PROXY_PROTOCOL_1, TEST_PROXY_ADDRESS_1,
TEST_PROXY_PROTOCOL_2, TEST_PROXY_ADDRESS_2)).toMatch(EXPECTED_PAC_CONTENT);
});
41 changes: 41 additions & 0 deletions tools/_regex_utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
function urls2regexs(urlList) {
const regexList = [];

for (let str of urlList) {
// Escape all possibly problematic symbols
// http://stackoverflow.com/a/6969486/1766096
str = str.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, '\\$&');
str = str.replace(/\*/g, '.*');

// make the first * matches only domain names or ip addresses
// just as http://developer.chrome.com/extensions/match_patterns.html
str = str.replace(/^http:\\\/\\\/\.\*/i, 'http:\\/\\/[^\/]*');
str = str.replace(/^https:\\\/\\\/\.\*/i, 'https:\\/\\/[^\/]*');

regexList.push(new RegExp('^' + str + '$', 'i'));
}

// console.log(regex_list);
return regexList;
}


export function produceSquidRegexList(urlList) {
const regexList = urls2regexs(urlList);
const regexToExtractHttpsDomain = /^\^https:\\\/\\\/([^:]+)\\\//i;

let str;
const result = [];
for (const regex of regexList) {
str = regex.toString();
str = str.substring(1, str.length - 2);

if (str.match(regexToExtractHttpsDomain)) {
str = '^' + str.match(regexToExtractHttpsDomain)[1] + ':443';
}

result.push(str);
}

return result;
}
Loading

0 comments on commit 0212c9e

Please sign in to comment.