123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- /* 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, 'TRACE_CALLS'))
- global.TRACE_CALLS = null;
- let _fs = require("fs");
- /* Force reloading fs module on next require */
- delete global.modules.fs;
- let _log = (level, fmt, ...args) => {
- let color, prefix;
- switch (level) {
- case 'info':
- color = 34;
- prefix = '!';
- break;
- case 'warn':
- color = 33;
- prefix = 'W';
- break;
- case 'error':
- color = 31;
- prefix = 'E';
- break;
- 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 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();
- return data;
- }
- }
- return null;
- };
- let read_json_file = (path) => {
- let data = read_data_file(path);
- if (data != null) {
- try {
- return json(data);
- }
- catch (e) {
- _log('error', "Unable to parse JSON data in %s: %s", path, e);
- return NaN;
- }
- }
- return null;
- };
- let format_json = (data) => {
- let rv;
- let format_value = (value) => {
- switch (type(value)) {
- case "object":
- return sprintf("{ /* %d keys */ }", length(value));
- case "array":
- return sprintf("[ /* %d items */ ]", length(value));
- case "string":
- if (length(value) > 64)
- value = substr(value, 0, 64) + "...";
- /* fall through */
- return sprintf("%J", value);
- default:
- return sprintf("%J", value);
- }
- };
- switch (type(data)) {
- case "object":
- rv = "{";
- let k = sort(keys(data));
- for (let i, n in k)
- rv += sprintf("%s %J: %s", i ? "," : "", n, format_value(data[n]));
- rv += " }";
- break;
- case "array":
- rv = "[";
- for (let i, v in data)
- rv += (i ? "," : "") + " " + format_value(v);
- rv += " ]";
- break;
- default:
- rv = format_value(data);
- }
- return rv;
- };
- let trace_call = (ns, func, args) => {
- let msg = "[call] " +
- (ns ? ns + "." : "") +
- func;
- for (let k, v in args) {
- msg += ' ' + k + ' <';
- switch (type(v)) {
- case "array":
- case "object":
- msg += format_json(v);
- break;
- default:
- msg += v;
- }
- msg += '>';
- }
- switch (TRACE_CALLS) {
- case '1':
- case 'stdout':
- _fs.stdout.write(msg + "\n");
- break;
- 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 = [ replace(path, /mocklib\.uc$/, '../mocks') ];
- unshift(REQUIRE_SEARCH_PATH, replace(path, /mocklib\.uc$/, 'mocklib/*.uc'));
- break;
- }
- if (type(MOCK_SEARCH_PATH) != 'array' || length(MOCK_SEARCH_PATH) == 0)
- MOCK_SEARCH_PATH = [ './mocks' ];
- let _print = global.print;
- /* Register global mocklib namespace */
- global.mocklib = {
- require: function(module) {
- let path, res, ex;
- if (type(REQUIRE_SEARCH_PATH) == "array" && index(REQUIRE_SEARCH_PATH[0], 'mocklib/*.uc') != -1)
- path = shift(REQUIRE_SEARCH_PATH);
- try {
- res = require(module);
- }
- catch (e) {
- ex = e;
- }
- if (path)
- unshift(REQUIRE_SEARCH_PATH, path);
- if (ex)
- die(ex);
- return res;
- },
- I: (...args) => _log('info', ...args),
- N: (...args) => _log('notice', ...args),
- W: (...args) => _log('warn', ...args),
- E: (...args) => _log('error', ...args),
- format_json,
- read_data_file,
- read_json_file,
- trace_call
- };
- /* Override stdlib functions */
- global.system = function(argv, timeout) {
- trace_call(null, "system", { command: argv, timeout });
- return 0;
- };
- 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;
|