Skip to content

Commit

Permalink
update the tests and add a check for rules not in the base syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
jellizaveta committed May 3, 2024
1 parent d18e4b8 commit a31621b
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 26 deletions.
2 changes: 2 additions & 0 deletions src/main/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ module.exports = (function () {

const NOT_OPTIMIZED_HINT = '!+ NOT_OPTIMIZED';

// TODO: Move include directive option functions to utils/builder-utils.js

/**
* Sync reads file content
*
Expand Down
56 changes: 31 additions & 25 deletions src/main/utils/builder-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,28 @@ const DOT = '.';
const optimizeBaseRules = function (lines) {
/**
* Modifies string to handle domains without rule markers
* @param {string} rule Rule in base adblock syntax.
* @returns {string} Domain without base rule markers.
*
* @param {string} rule - Rule in base adblock syntax.
* @returns {string} - Domain without base rule markers.
*/
const removeRuleMarkers = (rule) => rule
.replace(RuleMasks.MASK_BASE_RULE, '')
.replace(RuleMasks.MASK_RULE_SEPARATOR, '');

/**
* Checks if the line is in base rule style syntax
*
* @param {*} rule - Rule to check.
* @returns {boolean} - True if the rule is in base rule style syntax.
*/
const isBaseRule = (rule) => rule.startsWith(RuleMasks.MASK_BASE_RULE)
&& rule.endsWith(RuleMasks.MASK_RULE_SEPARATOR);

/**
* Extracts all possible domains from the input domain.
*
* @param {string} rawDomain Raw domain.
*
* @return {string[]} Array of possible domains, e.g.,
* @returns {string[]} Array of possible domains, e.g.,
* for `sub.example.com` -> `['sub.example.com', 'example.com', 'com']`.
*/
const extractDomainNames = (rawDomain) => {
Expand All @@ -44,24 +53,32 @@ const optimizeBaseRules = function (lines) {

/**
* Stores a map of domains and their subdomains.
*
* @type {Object.<string, string[]>}
* @example: { 'example.com': ['example', 'com'] }
*/
const domainsMap = {};

// Fill the domains map from base rule lines
// Stores non-base rule domains
const nonBaseRuleDomains = [];

// Fill the domains map from base rule lines, skip non-base rules
// and store them separately
lines.forEach((line) => {
if (!isBaseRule(line)) {
nonBaseRuleDomains.push(line);
return;
}
const domain = removeRuleMarkers(line);
const [fullDomain, ...domainParts] = extractDomainNames(domain);
domainsMap[fullDomain] = domainParts;
});

// Stores domains that are wider than other domains
const widerDomains = [];
// Stores domains that are redundant by wider domains
const redundantDomains = [];
const fullDomainNames = Object.keys(domainsMap);

// Stores keys with wider rules
const widerDomains = { ...domainsMap };

// Identify wider and redundant domains
fullDomainNames.forEach((currentDomain) => {
fullDomainNames.forEach((checkedDomain) => {
Expand All @@ -72,33 +89,22 @@ const optimizeBaseRules = function (lines) {
const subdomains = domainsMap[checkedDomain];
// If the current domain is found in the subdomains of another domain
if (subdomains.includes(currentDomain)) {
// If current domain is not already in wider domains, add it
if (!widerDomains.includes(currentDomain)) {
widerDomains.push(currentDomain);
}
// If checked domain is not already in redundant domains, add it
if (!redundantDomains.includes(checkedDomain)) {
redundantDomains.push(checkedDomain);
}
// remove redundant domain from copy of domainsMap
delete widerDomains[checkedDomain];
}
});
});

// If domain is not wider or redundant, add it to the rest domains
const restDomains = Object.keys(domainsMap)
.filter((domain) => !redundantDomains.includes(domain) && !widerDomains.includes(domain));

// Merge wider and rest domains
const optimizedDomains = [...widerDomains, ...restDomains];

/**
* Converts domain to base rule style syntax
* @param {string} domain - Domain name.
* @returns {string} - Domain with base rule markers.
*/
const addRuleMarkers = (domain) => `${RuleMasks.MASK_BASE_RULE}${domain}${RuleMasks.MASK_RULE_SEPARATOR}`;

return optimizedDomains.map(addRuleMarkers);
const optimizedBaseRules = Object.keys(widerDomains).map(addRuleMarkers);

return [...optimizedBaseRules, ...nonBaseRuleDomains];
};

module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion src/test/builder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('Test builder', () => {
expect(revision.timeUpdated).toBeTruthy();
});

describe('removeRedundant options of include directive', () => {
describe('optimizeBaseRules options of include directive', () => {
it('Should filter "platforms/mac" with "12.txt"', async () => {
// Read the content of the file and split it into lines
const filterContent = await readFile(path.join(platformsDir, 'mac', 'filters', '12.txt'));
Expand Down
48 changes: 48 additions & 0 deletions src/test/utils/builder-utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const { optimizeBaseRules } = require('../../main/utils/builder-utils');

jest.mock('../../main/utils/log');

describe('optimizeBaseRules options of include directive', () => {
it('Properly removes redundant rules', () => {
const lines = [
'||example.com^',
'||sub.example.com^',
'||sub2.sub.example.com^',
'||anotherexample.com^',
];
const expectedOutput = ['||example.com^', '||anotherexample.com^'];
const result = optimizeBaseRules(lines);
expect(result).toEqual(expectedOutput);
});

it('Returns all rules if there are no redundant rules', () => {
const lines = [
'||example.com^',
'||anotherexample.com^',
];
const expectedOutput = ['||example.com^', '||anotherexample.com^'];
const result = optimizeBaseRules(lines);
expect(result).toEqual(expectedOutput);
});

it('Skips rules that should not be optimized', () => {
const lines = [
'||example.com^',
'||sub.example.com^',
'||sub2.sub.example.com^',
'||some.anotherexample.com^',
'||anotherexample.com^$image',
'host.com',
];
const expectedOutput = [
'||example.com^',
'||some.anotherexample.com^',
'||anotherexample.com^$image',
'host.com',
];
const result = optimizeBaseRules(lines);
expectedOutput.forEach((rule) => {
expect(result.includes(rule)).toBeTruthy();
});
});
});

0 comments on commit a31621b

Please sign in to comment.