69d25615faaaee94c23e8e06cb9ea1ebc0f18715
[project/firewall4.git] / tests / lib / mocklib / uci.uc
1 {%
2 let mocklib = global.mocklib;
3
4 let hash = (s) => {
5 let h = 7;
6
7 for (let i = 0; i < length(s); i++)
8 h = h * 31 + ord(s, i)[0];
9
10 return h;
11 };
12
13 let id = (config, t, n) => {
14 while (true) {
15 let id = sprintf('cfg%08x', hash(t + n));
16
17 if (!exists(config, id))
18 return id;
19
20 n++;
21 }
22 };
23
24 let fixup_config = (config) => {
25 let rv = {};
26 let n_section = 0;
27
28 for (let stype in config) {
29 switch (type(config[stype])) {
30 case 'object':
31 config[stype] = [ config[stype] ];
32 /* fall through */
33
34 case 'array':
35 for (let idx, sobj in config[stype]) {
36 let sid, anon;
37
38 if (exists(sobj, '.name') && !exists(rv, sobj['.name'])) {
39 sid = sobj['.name'];
40 anon = false;
41 }
42 else {
43 sid = id(rv, stype, idx);
44 anon = true;
45 }
46
47 rv[sid] = {
48 '.index': n_section++,
49 ...sobj,
50 '.name': sid,
51 '.type': stype,
52 '.anonymous': anon
53 };
54 }
55
56 break;
57 }
58 }
59
60 for (let n, sid in sort(keys(rv), (a, b) => rv[a]['.index'] - rv[b]['.index']))
61 rv[sid]['.index'] = n;
62
63 return rv;
64 };
65
66 return {
67 cursor: () => ({
68 _configs: {},
69
70 load: function(file) {
71 let basename = replace(file, /^.+\//, ''),
72 path = sprintf("uci/%s.json", basename),
73 mock = mocklib.read_json_file(path);
74
75 if (!mock || mock != mock) {
76 mocklib.I("No configuration fixture defined for uci package %s.", file);
77 mocklib.I("Provide a mock configuration through the following JSON file:\n%s\n", path);
78
79 return null;
80 }
81
82 this._configs[basename] = fixup_config(mock);
83 },
84
85 _get_section: function(config, section) {
86 if (!exists(this._configs, config)) {
87 this.load(config);
88
89 if (!exists(this._configs, config))
90 return null;
91 }
92
93 let cfg = this._configs[config],
94 extended = match(section, "^@([A-Za-z0-9_-]+)\[(-?[0-9]+)\]$");
95
96 if (extended) {
97 let stype = extended[1],
98 sindex = +extended[2];
99
100 let sids = sort(
101 filter(keys(cfg), sid => cfg[sid]['.type'] == stype),
102 (a, b) => cfg[a]['.index'] - cfg[b]['.index']
103 );
104
105 if (sindex < 0)
106 sindex = sids.length + sindex;
107
108 return cfg[sids[sindex]];
109 }
110
111 return cfg[section];
112 },
113
114 get: function(config, section, option) {
115 let sobj = this._get_section(config, section);
116
117 if (option && index(option, ".") == 0)
118 return null;
119 else if (sobj && option)
120 return sobj[option];
121 else if (sobj)
122 return sobj[".type"];
123 },
124
125 get_all: function(config, section) {
126 return section ? this._get_section(config, section) : this._configs[config];
127 },
128
129 foreach: function(config, stype, cb) {
130 let rv = false;
131
132 if (exists(this._configs, config)) {
133 let cfg = this._configs[config],
134 sids = sort(keys(cfg), (a, b) => cfg[a]['.index'] - cfg[b]['.index']);
135
136 for (let i, sid in sids) {
137 if (stype == null || cfg[sid]['.type'] == stype) {
138 if (cb({ ...(cfg[sid]) }) === false)
139 break;
140
141 rv = true;
142 }
143 }
144 }
145
146 return rv;
147 }
148 })
149 };