Files
packages/net/adblock-fast/tests/lib/mocklib/uci.uc
T
Stan Grishin f64dd10a41 adblock-fast: update to 1.2.2-18
* Switch Hagezi URL to a more compact higher-level only domains list as we
  prefer it anyways and there's less processing (thanks @dave14305)
* When update_config_sizes is unset, save collected sizes to RAM to improve
  luci app performance (thanks @sshaikh)

Signed-off-by: Stan Grishin <stangri@melmac.ca>
2026-04-24 18:27:12 -07:00

214 lines
4.6 KiB
Ucode

// UCI mock for adblock-fast tests.
// Based on mwan4's UCI mock, extended with set/save/commit/changes/delete.
let mocklib = global.mocklib; // ucode-lsp disable
let byte = (str, off) => { // ucode-lsp disable
let v = ord(str, off);
return type(v) == 'array' ? v[0] : v;
};
let hash = (s) => { // ucode-lsp disable
let h = 7;
for (let i = 0; i < length(s); i++)
h = h * 31 + byte(s, i);
return h;
};
let id = (config, t, n) => { // ucode-lsp disable
while (true) {
let id = sprintf('cfg%08x', hash(t + n));
if (!exists(config, id))
return id;
n++;
}
};
let fixup_config = (config) => { // ucode-lsp disable
let rv = {};
let n_section = 0;
for (let stype in config) {
switch (type(config[stype])) {
case 'object':
config[stype] = [ config[stype] ];
/* fall through */
case 'array':
for (let idx, sobj in config[stype]) {
let sid, anon;
if (exists(sobj, '.name') && !exists(rv, sobj['.name'])) {
sid = sobj['.name'];
anon = false;
}
else {
sid = id(rv, stype, idx);
anon = true;
}
rv[sid] = {
'.index': n_section++,
...sobj,
'.name': sid,
'.type': stype,
'.anonymous': anon
};
}
break;
}
}
for (let n, sid in sort(keys(rv), (a, b) => rv[a]['.index'] - rv[b]['.index']))
rv[sid]['.index'] = n;
return rv;
};
return {
cursor: () => ({
_configs: {},
_dirty: {},
load: function(file) {
let basename = replace(file, /^.+\//, ''),
path = sprintf("uci/%s.json", basename),
mock = mocklib.read_json_file(path);
if (!mock || mock != mock) {
mocklib.I("No configuration fixture defined for uci package %s.", file);
mocklib.I("Provide a mock configuration through the following JSON file:\n%s\n", path);
return null;
}
this._configs[basename] = fixup_config(mock);
},
_get_section: function(config, section) {
if (!exists(this._configs, config)) {
this.load(config);
if (!exists(this._configs, config))
return null;
}
let cfg = this._configs[config],
extended = match('' + section, /^@([A-Za-z0-9_-]+)\[(-?[0-9]+)\]$/);
if (extended) {
let stype = extended[1],
sindex = +extended[2];
let sids = sort(
filter(keys(cfg), sid => cfg[sid]['.type'] == stype),
(a, b) => cfg[a]['.index'] - cfg[b]['.index']
);
if (sindex < 0)
sindex = length(sids) + sindex;
return cfg[sids[sindex]];
}
return cfg[section];
},
get: function(config, section, option) {
let sobj = this._get_section(config, section);
if (option && index(option, ".") == 0)
return null;
else if (sobj && option)
return sobj[option];
else if (sobj)
return sobj[".type"];
},
get_all: function(config, section) {
return section ? this._get_section(config, section) : this._configs[config];
},
foreach: function(config, stype, cb) {
let rv = false;
if (!exists(this._configs, config))
this.load(config);
if (exists(this._configs, config)) {
let cfg = this._configs[config],
sids = sort(keys(cfg), (a, b) => cfg[a]['.index'] - cfg[b]['.index']);
for (let i, sid in sids) {
if (stype == null || cfg[sid]['.type'] == stype) {
if (cb({ ...(cfg[sid]) }) === false)
break;
rv = true;
}
}
}
return rv;
},
// -- Extensions for adblock-fast --
set: function(config, section, option, value) {
let sobj = this._get_section(config, section);
if (sobj) {
sobj[option] = value;
this._dirty[config] = true;
}
},
save: function(config) {
return true;
},
commit: function(config) {
delete this._dirty[config];
return true;
},
changes: function(config) {
return this._dirty[config] ? [['set']] : [];
},
revert: function(config) {
delete this._dirty[config];
},
delete: function(config, section, option) {
if (option) {
let sobj = this._get_section(config, section);
if (sobj) delete sobj[option];
} else if (section) {
if (exists(this._configs, config))
delete this._configs[config][section];
}
},
list_add: function(config, section, option, value) {
let sobj = this._get_section(config, section);
if (!sobj) return;
if (type(sobj[option]) != 'array')
sobj[option] = sobj[option] ? [sobj[option]] : [];
push(sobj[option], value);
this._dirty[config] = true;
},
list_remove: function(config, section, option, value) {
let sobj = this._get_section(config, section);
if (!sobj || type(sobj[option]) != 'array') return;
sobj[option] = filter(sobj[option], v => v != value);
this._dirty[config] = true;
},
})
};