esac
ACTION=start \
- ucode -S -i $MAIN | nft $VERBOSE -f /proc/self/fd/0
+ utpl -S $MAIN | nft $VERBOSE -f /proc/self/fd/0
} 1000>$LOCK
}
print() {
ACTION=print \
- ucode -S -i $MAIN
+ utpl -S $MAIN
}
stop() {
reload_sets() {
ACTION=reload-sets \
- flock -x $LOCK ucode -S -i $MAIN | nft $VERBOSE -f /proc/self/fd/0
+ flock -x $LOCK utpl -S $MAIN | nft $VERBOSE -f /proc/self/fd/0
}
lookup() {
ACTION=$1 OBJECT=$2 DEVICE=$3 \
- flock -x $LOCK ucode -S -i $MAIN
+ flock -x $LOCK utpl -S $MAIN
}
while [ -n "$1" ]; do
-{%
-
let fs = require("fs");
let uci = require("uci");
let ubus = require("ubus");
#!/usr/bin/env bash
line='........................................'
-uenv='{
- "REQUIRE_SEARCH_PATH": [
- "./tests/lib/*.uc",
- "./root/usr/share/ucode/*.uc",
- "/usr/local/lib/ucode/*.so",
- "/usr/lib/ucode/*.so"
- ]
-}'
+ucode='ucode -S -T, -L./tests/lib -L./root/usr/share/ucode'
extract_sections() {
local file=$1
local code=$7
local fail=0
- ucode -S ${uenv:+-e "$uenv"} -e '{
- "MOCK_SEARCH_PATH": [
- "'"$dir"'/files",
- "./tests/mocks"
- ]
- }' ${env:+-e "$(cat "$env")"} -m mocklib -m fw4 -i - <"$in" >"$dir/res.out" 2>"$dir/res.err"
+ $ucode \
+ -D MOCK_SEARCH_PATH='["'"$dir"'/files", "./tests/mocks"]' \
+ ${env:+-F "$env"} \
+ -l mocklib -l fw4 \
+ - <"$in" >"$dir/res.out" 2>"$dir/res.err"
printf "%d\n" $? > "$dir/res.code"
-{%
- /* strict mode compliance: ensure that global variabes are defined */
- if (!exists(global, 'REQUIRE_SEARCH_PATH'))
- global.MOCK_SEARCH_PATH = null;
+/* strict mode compliance: ensure that global variabes are defined */
+if (!exists(global, 'REQUIRE_SEARCH_PATH'))
+ global.MOCK_SEARCH_PATH = null;
- if (!exists(global, 'MOCK_SEARCH_PATH'))
- global.MOCK_SEARCH_PATH = null;
+if (!exists(global, 'MOCK_SEARCH_PATH'))
+ global.MOCK_SEARCH_PATH = null;
- if (!exists(global, 'TRACE_CALLS'))
- global.TRACE_CALLS = null;
+if (!exists(global, 'TRACE_CALLS'))
+ global.TRACE_CALLS = null;
- let _fs = require("fs");
+let _fs = require("fs");
- /* Force reloading fs module on next require */
- delete global.modules.fs;
+/* Force reloading fs module on next require */
+delete global.modules.fs;
- let _log = (level, fmt, ...args) => {
- let color, prefix;
+let _log = (level, fmt, ...args) => {
+ let color, prefix;
- switch (level) {
- case 'info':
- color = 34;
- prefix = '!';
- break;
+ switch (level) {
+ case 'info':
+ color = 34;
+ prefix = '!';
+ break;
- case 'warn':
- color = 33;
- prefix = 'W';
- break;
+ case 'warn':
+ color = 33;
+ prefix = 'W';
+ break;
- case 'error':
- color = 31;
- prefix = 'E';
- break;
+ case 'error':
+ color = 31;
+ prefix = 'E';
+ break;
- default:
- color = 0;
- prefix = 'I';
- }
+ default:
+ color = 0;
+ prefix = 'I';
+ }
- let f = sprintf("\u001b[%d;1m[%s] %s\u001b[0m", color, prefix, fmt);
- warn(replace(sprintf(f, ...args), "\n", "\n "), "\n");
- };
+ let f = sprintf("\u001b[%d;1m[%s] %s\u001b[0m", color, prefix, fmt);
+ warn(replace(sprintf(f, ...args), "\n", "\n "), "\n");
+};
- let read_data_file = (path) => {
- for (let dir in MOCK_SEARCH_PATH) {
- let fd = _fs.open(dir + '/' + path, "r");
+let read_data_file = (path) => {
+ for (let dir in MOCK_SEARCH_PATH) {
+ let fd = _fs.open(dir + '/' + path, "r");
- if (fd) {
- let data = fd.read("all");
- fd.close();
+ if (fd) {
+ let data = fd.read("all");
+ fd.close();
- return data;
- }
+ return data;
}
+ }
- return null;
- };
-
- let read_json_file = (path) => {
- let data = read_data_file(path);
+ return null;
+};
- if (data != null) {
- try {
- return json(data);
- }
- catch (e) {
- _log('error', "Unable to parse JSON data in %s: %s", path, e);
+let read_json_file = (path) => {
+ let data = read_data_file(path);
- return NaN;
- }
+ if (data != null) {
+ try {
+ return json(data);
}
+ catch (e) {
+ _log('error', "Unable to parse JSON data in %s: %s", path, e);
- return null;
- };
-
- let format_json = (data) => {
- let rv;
-
- let format_value = (value) => {
- switch (type(value)) {
- case "object":
- return sprintf("{ /* %d keys */ }", length(value));
+ return NaN;
+ }
+ }
- case "array":
- return sprintf("[ /* %d items */ ]", length(value));
+ return null;
+};
- case "string":
- if (length(value) > 64)
- value = substr(value, 0, 64) + "...";
+let format_json = (data) => {
+ let rv;
- /* fall through */
- return sprintf("%J", value);
+ let format_value = (value) => {
+ switch (type(value)) {
+ case "object":
+ return sprintf("{ /* %d keys */ }", length(value));
- default:
- return sprintf("%J", value);
- }
- };
+ case "array":
+ return sprintf("[ /* %d items */ ]", length(value));
- switch (type(data)) {
- case "object":
- rv = "{";
+ case "string":
+ if (length(value) > 64)
+ value = substr(value, 0, 64) + "...";
- let k = sort(keys(data));
+ /* fall through */
+ return sprintf("%J", value);
- for (let i, n in k)
- rv += sprintf("%s %J: %s", i ? "," : "", n, format_value(data[n]));
+ default:
+ return sprintf("%J", value);
+ }
+ };
- rv += " }";
- break;
+ switch (type(data)) {
+ case "object":
+ rv = "{";
- case "array":
- rv = "[";
+ let k = sort(keys(data));
- for (let i, v in data)
- rv += (i ? "," : "") + " " + format_value(v);
+ for (let i, n in k)
+ rv += sprintf("%s %J: %s", i ? "," : "", n, format_value(data[n]));
- rv += " ]";
- break;
+ rv += " }";
+ break;
- default:
- rv = format_value(data);
- }
+ case "array":
+ rv = "[";
- return rv;
- };
+ for (let i, v in data)
+ rv += (i ? "," : "") + " " + format_value(v);
- let trace_call = (ns, func, args) => {
- let msg = "[call] " +
- (ns ? ns + "." : "") +
- func;
+ rv += " ]";
+ break;
- for (let k, v in args) {
- msg += ' ' + k + ' <';
+ default:
+ rv = format_value(data);
+ }
- switch (type(v)) {
- case "array":
- case "object":
- msg += format_json(v);
- break;
+ return rv;
+};
- default:
- msg += v;
- }
+let trace_call = (ns, func, args) => {
+ let msg = "[call] " +
+ (ns ? ns + "." : "") +
+ func;
- msg += '>';
- }
+ for (let k, v in args) {
+ msg += ' ' + k + ' <';
- switch (TRACE_CALLS) {
- case '1':
- case 'stdout':
- _fs.stdout.write(msg + "\n");
+ switch (type(v)) {
+ case "array":
+ case "object":
+ msg += format_json(v);
break;
- case 'stderr':
- _fs.stderr.write(msg + "\n");
- break;
+ default:
+ msg += v;
}
- };
-
- /* Prepend mocklib to REQUIRE_SEARCH_PATH */
- for (let pattern in REQUIRE_SEARCH_PATH) {
- /* Only consider ucode includes */
- if (!match(pattern, /\*\.uc$/))
- continue;
-
- let path = replace(pattern, /\*/, 'mocklib'),
- stat = _fs.stat(path);
- if (!stat || stat.type != 'file')
- continue;
+ msg += '>';
+ }
- if (type(MOCK_SEARCH_PATH) != 'array' || length(MOCK_SEARCH_PATH) == 0)
- MOCK_SEARCH_PATH = [ replace(path, /mocklib\.uc$/, '../mocks') ];
+ switch (TRACE_CALLS) {
+ case '1':
+ case 'stdout':
+ _fs.stdout.write(msg + "\n");
+ break;
- unshift(REQUIRE_SEARCH_PATH, replace(path, /mocklib\.uc$/, 'mocklib/*.uc'));
+ case 'stderr':
+ _fs.stderr.write(msg + "\n");
break;
}
+};
+
+/* Prepend mocklib to REQUIRE_SEARCH_PATH */
+for (let pattern in REQUIRE_SEARCH_PATH) {
+ /* Only consider ucode includes */
+ if (!match(pattern, /\*\.uc$/))
+ continue;
+
+ let path = replace(pattern, /\*/, 'mocklib'),
+ stat = _fs.stat(path);
+
+ if (!stat || stat.type != 'file')
+ continue;
if (type(MOCK_SEARCH_PATH) != 'array' || length(MOCK_SEARCH_PATH) == 0)
- MOCK_SEARCH_PATH = [ './mocks' ];
+ MOCK_SEARCH_PATH = [ replace(path, /mocklib\.uc$/, '../mocks') ];
- let _print = global.print;
+ unshift(REQUIRE_SEARCH_PATH, replace(path, /mocklib\.uc$/, 'mocklib/*.uc'));
+ break;
+}
- /* Register global mocklib namespace */
- global.mocklib = {
- require: function(module) {
- let path, res, ex;
+if (type(MOCK_SEARCH_PATH) != 'array' || length(MOCK_SEARCH_PATH) == 0)
+ MOCK_SEARCH_PATH = [ './mocks' ];
- if (type(REQUIRE_SEARCH_PATH) == "array" && index(REQUIRE_SEARCH_PATH[0], 'mocklib/*.uc') != -1)
- path = shift(REQUIRE_SEARCH_PATH);
+let _print = global.print;
- try {
- res = require(module);
- }
- catch (e) {
- ex = e;
- }
+/* Register global mocklib namespace */
+global.mocklib = {
+ require: function(module) {
+ let path, res, ex;
- if (path)
- unshift(REQUIRE_SEARCH_PATH, path);
+ if (type(REQUIRE_SEARCH_PATH) == "array" && index(REQUIRE_SEARCH_PATH[0], 'mocklib/*.uc') != -1)
+ path = shift(REQUIRE_SEARCH_PATH);
- if (ex)
- die(ex);
+ try {
+ res = require(module);
+ }
+ catch (e) {
+ ex = e;
+ }
- return res;
- },
+ if (path)
+ unshift(REQUIRE_SEARCH_PATH, path);
- I: (...args) => _log('info', ...args),
- N: (...args) => _log('notice', ...args),
- W: (...args) => _log('warn', ...args),
- E: (...args) => _log('error', ...args),
+ if (ex)
+ die(ex);
- format_json,
- read_data_file,
- read_json_file,
- trace_call
- };
+ return res;
+ },
- /* Override stdlib functions */
- global.system = function(argv, timeout) {
- trace_call(null, "system", { command: argv, timeout });
+ I: (...args) => _log('info', ...args),
+ N: (...args) => _log('notice', ...args),
+ W: (...args) => _log('warn', ...args),
+ E: (...args) => _log('error', ...args),
- return 0;
- };
+ format_json,
+ read_data_file,
+ read_json_file,
+ trace_call
+};
- global.time = function() {
- trace_call(null, "time");
+/* Override stdlib functions */
+global.system = function(argv, timeout) {
+ trace_call(null, "system", { command: argv, timeout });
- return 1615382640;
- };
+ return 0;
+};
- global.print = function(...args) {
- if (length(args) == 1 && type(args[0]) in ["array", "object"])
- printf("%s\n", format_json(args[0]));
- else
- _print(...args);
- };
+global.time = function() {
+ trace_call(null, "time");
+
+ return 1615382640;
+};
+
+global.print = function(...args) {
+ if (length(args) == 1 && type(args[0]) in ["array", "object"])
+ printf("%s\n", format_json(args[0]));
+ else
+ _print(...args);
+};
- return global.mocklib;
+return global.mocklib;
-{%
- let mocklib = global.mocklib,
- fs = mocklib.require("fs");
-
- return {
- readlink: function(path) {
- mocklib.trace_call("fs", "readlink", { path });
-
- return path + "-link";
- },
-
- stat: function(path) {
- let file = sprintf("fs/stat~%s.json", replace(path, /[^A-Za-z0-9_-]+/g, '_')),
- mock = mocklib.read_json_file(file);
-
- if (!mock || mock != mock) {
- mocklib.I("No stat result fixture defined for fs.stat() call on %s.", path);
- mocklib.I("Provide a mock result through the following JSON file:\n%s\n", file);
-
- if (match(path, /\/$/))
- mock = { type: "directory" };
- else
- mock = { type: "file" };
- }
-
- mocklib.trace_call("fs", "stat", { path });
-
- return mock;
- },
-
- unlink: function(path) {
- printf("fs.unlink() path <%s>\n", path);
-
- return true;
- },
+let mocklib = global.mocklib,
+ fs = mocklib.require("fs");
+
+return {
+ readlink: function(path) {
+ mocklib.trace_call("fs", "readlink", { path });
+
+ return path + "-link";
+ },
+
+ stat: function(path) {
+ let file = sprintf("fs/stat~%s.json", replace(path, /[^A-Za-z0-9_-]+/g, '_')),
+ mock = mocklib.read_json_file(file);
+
+ if (!mock || mock != mock) {
+ mocklib.I("No stat result fixture defined for fs.stat() call on %s.", path);
+ mocklib.I("Provide a mock result through the following JSON file:\n%s\n", file);
+
+ if (match(path, /\/$/))
+ mock = { type: "directory" };
+ else
+ mock = { type: "file" };
+ }
+
+ mocklib.trace_call("fs", "stat", { path });
+
+ return mock;
+ },
+
+ unlink: function(path) {
+ printf("fs.unlink() path <%s>\n", path);
+
+ return true;
+ },
+
+ popen: (cmdline, mode) => {
+ let read = (!mode || index(mode, "r") != -1),
+ path = sprintf("fs/popen~%s.txt", replace(cmdline, /[^A-Za-z0-9_-]+/g, '_')),
+ mock = mocklib.read_data_file(path);
+
+ if (read && !mock) {
+ mocklib.I("No stdout fixture defined for fs.popen() command %s.", cmdline);
+ mocklib.I("Provide a mock output through the following text file:\n%s\n", path);
+
+ return null;
+ }
+
+ mocklib.trace_call("fs", "popen", { cmdline, mode });
+
+ return {
+ read: function(amount) {
+ let rv;
+
+ switch (amount) {
+ case "all":
+ rv = mock;
+ mock = "";
+ break;
+
+ case "line":
+ let i = index(mock, "\n");
+ i = (i > -1) ? i + 1 : mock.length;
+ rv = substr(mock, 0, i);
+ mock = substr(mock, i);
+ break;
+
+ default:
+ let n = +amount;
+ n = (n > 0) ? n : 0;
+ rv = substr(mock, 0, n);
+ mock = substr(mock, n);
+ break;
+ }
- popen: (cmdline, mode) => {
- let read = (!mode || index(mode, "r") != -1),
- path = sprintf("fs/popen~%s.txt", replace(cmdline, /[^A-Za-z0-9_-]+/g, '_')),
- mock = mocklib.read_data_file(path);
+ return rv;
+ },
- if (read && !mock) {
- mocklib.I("No stdout fixture defined for fs.popen() command %s.", cmdline);
- mocklib.I("Provide a mock output through the following text file:\n%s\n", path);
+ write: function() {},
+ close: function() {},
+ error: function() {
return null;
}
-
- mocklib.trace_call("fs", "popen", { cmdline, mode });
-
- return {
- read: function(amount) {
- let rv;
-
- switch (amount) {
- case "all":
- rv = mock;
- mock = "";
- break;
-
- case "line":
- let i = index(mock, "\n");
- i = (i > -1) ? i + 1 : mock.length;
- rv = substr(mock, 0, i);
- mock = substr(mock, i);
- break;
-
- default:
- let n = +amount;
- n = (n > 0) ? n : 0;
- rv = substr(mock, 0, n);
- mock = substr(mock, n);
- break;
- }
-
- return rv;
- },
-
- write: function() {},
- close: function() {},
-
- error: function() {
- return null;
+ };
+ },
+
+ open: (fpath, mode) => {
+ let read = (!mode || index(mode, "r") != -1 || index(mode, "+") != -1),
+ path = sprintf("fs/open~%s.txt", replace(fpath, /[^A-Za-z0-9_-]+/g, '_')),
+ mock = read ? mocklib.read_data_file(path) : null;
+
+ if (read && !mock) {
+ mocklib.I("No stdout fixture defined for fs.open() path %s.", fpath);
+ mocklib.I("Provide a mock output through the following text file:\n%s\n", path);
+
+ return null;
+ }
+
+ mocklib.trace_call("fs", "open", { path: fpath, mode });
+
+ return {
+ read: function(amount) {
+ let rv;
+
+ switch (amount) {
+ case "all":
+ rv = mock;
+ mock = "";
+ break;
+
+ case "line":
+ let i = index(mock, "\n");
+ i = (i > -1) ? i + 1 : mock.length;
+ rv = substr(mock, 0, i);
+ mock = substr(mock, i);
+ break;
+
+ default:
+ let n = +amount;
+ n = (n > 0) ? n : 0;
+ rv = substr(mock, 0, n);
+ mock = substr(mock, n);
+ break;
}
- };
- },
- open: (fpath, mode) => {
- let read = (!mode || index(mode, "r") != -1 || index(mode, "+") != -1),
- path = sprintf("fs/open~%s.txt", replace(fpath, /[^A-Za-z0-9_-]+/g, '_')),
- mock = read ? mocklib.read_data_file(path) : null;
+ return rv;
+ },
- if (read && !mock) {
- mocklib.I("No stdout fixture defined for fs.open() path %s.", fpath);
- mocklib.I("Provide a mock output through the following text file:\n%s\n", path);
+ write: function() {},
+ close: function() {},
+ error: function() {
return null;
}
+ };
+ },
- mocklib.trace_call("fs", "open", { path: fpath, mode });
-
- return {
- read: function(amount) {
- let rv;
-
- switch (amount) {
- case "all":
- rv = mock;
- mock = "";
- break;
-
- case "line":
- let i = index(mock, "\n");
- i = (i > -1) ? i + 1 : mock.length;
- rv = substr(mock, 0, i);
- mock = substr(mock, i);
- break;
-
- default:
- let n = +amount;
- n = (n > 0) ? n : 0;
- rv = substr(mock, 0, n);
- mock = substr(mock, n);
- break;
- }
-
- return rv;
- },
-
- write: function() {},
- close: function() {},
-
- error: function() {
- return null;
- }
- };
- },
+ opendir: (path) => {
+ let file = sprintf("fs/opendir~%s.json", replace(path, /[^A-Za-z0-9_-]+/g, '_')),
+ mock = mocklib.read_json_file(file),
+ index = 0;
- opendir: (path) => {
- let file = sprintf("fs/opendir~%s.json", replace(path, /[^A-Za-z0-9_-]+/g, '_')),
- mock = mocklib.read_json_file(file),
- index = 0;
+ if (!mock || mock != mock) {
+ mocklib.I("No stat result fixture defined for fs.opendir() call on %s.", path);
+ mocklib.I("Provide a mock result through the following JSON file:\n%s\n", file);
- if (!mock || mock != mock) {
- mocklib.I("No stat result fixture defined for fs.opendir() call on %s.", path);
- mocklib.I("Provide a mock result through the following JSON file:\n%s\n", file);
+ mock = [];
+ }
- mock = [];
- }
+ mocklib.trace_call("fs", "opendir", { path });
- mocklib.trace_call("fs", "opendir", { path });
+ return {
+ read: function() {
+ return mock[index++];
+ },
- return {
- read: function() {
- return mock[index++];
- },
+ tell: function() {
+ return index;
+ },
- tell: function() {
- return index;
- },
+ seek: function(i) {
+ index = i;
+ },
- seek: function(i) {
- index = i;
- },
+ close: function() {},
- close: function() {},
-
- error: function() {
- return null;
- }
- };
- },
+ error: function() {
+ return null;
+ }
+ };
+ },
- error: () => "Unspecified error"
- };
+ error: () => "Unspecified error"
+};
-{%
- let mocklib = global.mocklib;
-
- return {
- connect: function() {
- let self = this;
-
- return {
- call: (object, method, args) => {
- let signature = [ object + "~" + method ];
-
- if (type(args) == "object") {
- for (let i, k in sort(keys(args))) {
- switch (type(args[k])) {
- case "string":
- case "double":
- case "bool":
- case "int":
- push(signature, k + "-" + replace(args[k], /[^A-Za-z0-9_-]+/g, "_"));
- break;
-
- default:
- push(signature, type(args[k]));
- }
+let mocklib = global.mocklib;
+
+return {
+ connect: function() {
+ let self = this;
+
+ return {
+ call: (object, method, args) => {
+ let signature = [ object + "~" + method ];
+
+ if (type(args) == "object") {
+ for (let i, k in sort(keys(args))) {
+ switch (type(args[k])) {
+ case "string":
+ case "double":
+ case "bool":
+ case "int":
+ push(signature, k + "-" + replace(args[k], /[^A-Za-z0-9_-]+/g, "_"));
+ break;
+
+ default:
+ push(signature, type(args[k]));
}
}
+ }
- let candidates = [];
+ let candidates = [];
- for (let i = length(signature); i > 0; i--) {
- let path = sprintf("ubus/%s.json", join("~", signature)),
- mock = mocklib.read_json_file(path);
+ for (let i = length(signature); i > 0; i--) {
+ let path = sprintf("ubus/%s.json", join("~", signature)),
+ mock = mocklib.read_json_file(path);
- if (mock != mock) {
- self._error = "Invalid argument";
+ if (mock != mock) {
+ self._error = "Invalid argument";
- return null;
- }
- else if (mock) {
- mocklib.trace_call("ctx", "call", { object, method, args });
-
- return mock;
- }
+ return null;
+ }
+ else if (mock) {
+ mocklib.trace_call("ctx", "call", { object, method, args });
- push(candidates, path);
- pop(signature);
+ return mock;
}
- mocklib.I("No response fixture defined for ubus call %s/%s with arguments %s.", object, method, args);
- mocklib.I("Provide a mock response through one of the following JSON files:\n%s\n", join("\n", candidates));
+ push(candidates, path);
+ pop(signature);
+ }
+
+ mocklib.I("No response fixture defined for ubus call %s/%s with arguments %s.", object, method, args);
+ mocklib.I("Provide a mock response through one of the following JSON files:\n%s\n", join("\n", candidates));
- self._error = "Method not found";
+ self._error = "Method not found";
- return null;
- },
+ return null;
+ },
- disconnect: () => null,
+ disconnect: () => null,
- error: () => self.error()
- };
- },
+ error: () => self.error()
+ };
+ },
- error: function() {
- let e = this._error;
- delete this._error;
+ error: function() {
+ let e = this._error;
+ delete this._error;
- return e;
- }
- };
+ return e;
+ }
+};
-{%
- let mocklib = global.mocklib;
+let mocklib = global.mocklib;
- let byte = (str, off) => {
- let v = ord(str, off);
- return length(v) ? v[0] : v;
- };
+let byte = (str, off) => {
+ let v = ord(str, off);
+ return length(v) ? v[0] : v;
+};
- let hash = (s) => {
- let h = 7;
+let hash = (s) => {
+ let h = 7;
- for (let i = 0; i < length(s); i++)
- h = h * 31 + byte(s, i);
+ for (let i = 0; i < length(s); i++)
+ h = h * 31 + byte(s, i);
- return h;
- };
+ return h;
+};
- let id = (config, t, n) => {
- while (true) {
- let id = sprintf('cfg%08x', hash(t + n));
+let id = (config, t, n) => {
+ while (true) {
+ let id = sprintf('cfg%08x', hash(t + n));
- if (!exists(config, id))
- return id;
+ if (!exists(config, id))
+ return id;
- n++;
- }
- };
-
- let fixup_config = (config) => {
- let rv = {};
- let n_section = 0;
+ n++;
+ }
+};
- for (let stype in config) {
- switch (type(config[stype])) {
- case 'object':
- config[stype] = [ config[stype] ];
- /* fall through */
+let fixup_config = (config) => {
+ let rv = {};
+ let n_section = 0;
- case 'array':
- for (let idx, sobj in config[stype]) {
- let sid, anon;
+ for (let stype in config) {
+ switch (type(config[stype])) {
+ case 'object':
+ config[stype] = [ config[stype] ];
+ /* fall through */
- if (exists(sobj, '.name') && !exists(rv, sobj['.name'])) {
- sid = sobj['.name'];
- anon = false;
- }
- else {
- sid = id(rv, stype, idx);
- anon = true;
- }
+ case 'array':
+ for (let idx, sobj in config[stype]) {
+ let sid, anon;
- rv[sid] = {
- '.index': n_section++,
- ...sobj,
- '.name': sid,
- '.type': stype,
- '.anonymous': anon
- };
+ if (exists(sobj, '.name') && !exists(rv, sobj['.name'])) {
+ sid = sobj['.name'];
+ anon = false;
+ }
+ else {
+ sid = id(rv, stype, idx);
+ anon = true;
}
- break;
+ 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;
+ for (let n, sid in sort(keys(rv), (a, b) => rv[a]['.index'] - rv[b]['.index']))
+ rv[sid]['.index'] = n;
- return rv;
- };
+ return rv;
+};
- return {
- cursor: () => ({
- _configs: {},
+return {
+ cursor: () => ({
+ _configs: {},
- load: function(file) {
- let basename = replace(file, /^.+\//, ''),
- path = sprintf("uci/%s.json", basename),
- mock = mocklib.read_json_file(path);
+ 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);
+ 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;
- }
+ }
- this._configs[basename] = fixup_config(mock);
- },
+ let cfg = this._configs[config],
+ extended = match(section, "^@([A-Za-z0-9_-]+)\[(-?[0-9]+)\]$");
- _get_section: function(config, section) {
- if (!exists(this._configs, config)) {
- this.load(config);
+ if (extended) {
+ let stype = extended[1],
+ sindex = +extended[2];
- if (!exists(this._configs, config))
- return null;
- }
+ let sids = sort(
+ filter(keys(cfg), sid => cfg[sid]['.type'] == stype),
+ (a, b) => cfg[a]['.index'] - cfg[b]['.index']
+ );
- let cfg = this._configs[config],
- extended = match(section, "^@([A-Za-z0-9_-]+)\[(-?[0-9]+)\]$");
+ if (sindex < 0)
+ sindex = sids.length + sindex;
- if (extended) {
- let stype = extended[1],
- sindex = +extended[2];
+ return cfg[sids[sindex]];
+ }
- let sids = sort(
- filter(keys(cfg), sid => cfg[sid]['.type'] == stype),
- (a, b) => cfg[a]['.index'] - cfg[b]['.index']
- );
+ return cfg[section];
+ },
- if (sindex < 0)
- sindex = sids.length + sindex;
+ get: function(config, section, option) {
+ let sobj = this._get_section(config, section);
- return cfg[sids[sindex]];
- }
+ if (option && index(option, ".") == 0)
+ return null;
+ else if (sobj && option)
+ return sobj[option];
+ else if (sobj)
+ return sobj[".type"];
+ },
- return cfg[section];
- },
+ get_all: function(config, section) {
+ return section ? this._get_section(config, section) : this._configs[config];
+ },
- get: function(config, section, option) {
- let sobj = this._get_section(config, section);
+ foreach: function(config, stype, cb) {
+ let rv = false;
- 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)) {
- 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;
- }
+ 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;
}
- })
- };
+
+ return rv;
+ }
+ })
+};