1# Expected JSON Checker tool
2
3A tool that cross checks an expected set of JSON entries, by a given index,
4with a given input set of JSON entries. In addition, there's an ability to
5filter expected entries by using logical operations against entries within
6another file contain JSON entries. This filtering functionality on cross
7checking expected entries with a set of input is optional
8
9Expected entries that only want to be found within the input JSON should use
10a value of `{}`. This denotes the value for the given property should be
11treated as a `don't care` and ignored during the cross-check.
12
13## Intention:
14
15The intention for this tool's creation was to provide an ability to cross check
16entries within the BMC's enumerated sensor JSON output against an expected set
17of entries for a specific machine. In addition, the expected set of entries are
18different based on specific entries within inventory. So given a dump of a
19machine's enumerated sensor data and inventory data to separate JSON files,
20an expected set of entries that should be contained within the sensor data
21is created for this machine. These JSON files are then fed into this tool to
22determine if all the expected set of entries are found within the sensor data.
23The machine's name was used as the index into the expected JSON to allow the
24same expected JSON file to be used across multiple machines instead of having
25separate expected JSON files per machine(since what's expected will likely be
26different across different machines).
27
28## (OPTIONAL) Filtering:
29
30Filters can be used for whether or not a set of entries within the expected
31JSON file should be included when cross checking with the input set of JSON
32entries. This is useful in allowing a single set of expected entries to be
33used and add/remove entries based on some other JSON file's contents.
34
35### Supported logical operations:
36
37- \$and : Performs an AND operation on an array with at least two
38          expressions and returns the document that meets all the
39          expressions. i.e.) {"$and": [{"age": 5}, {"name": "Joe"}]}
40- \$or :  Performs an OR operation on an array with at least two
41          expressions and returns the documents that meet at least one of
42          the expressions. i.e.) {"$or": [{"age": 4}, {"name": "Joe"}]}
43- \$nor : Performs a NOR operation on an array with at least two
44          expressions and returns the documents that do not meet any of
45          the expressions. i.e.) {"$nor": [{"age": 3}, {"name": "Moe"}]}
46- \$not : Performs a NOT operation on the specified expression and
47          returns the documents that do not meet the expression.
48          i.e.) {"$not": {"age": 4}}
49
50## Example Usage:
51
52Expected JSON set of entries for a `witherspoon` index(expected.json):
53```
54{
55    "witherspoon": {
56        "/xyz/openbmc_project/sensors/fan_tach/fan0_0": {
57            "Functional": true,
58            "Target": {},
59            "Value": {}
60        },
61        "/xyz/openbmc_project/sensors/fan_tach/fan0_1": {
62            "Functional": true,
63            "Value": {}
64        },
65        "$op": {
66            "$and": [{
67                "/xyz/openbmc_project/inventory/system/chassis":{"WaterCooled": false}
68            }],
69            "$input": [{
70                "/xyz/openbmc_project/sensors/fan_tach/fan1_0": {
71                    "Functional": true,
72                    "Target": {},
73                    "Value": {}
74                },
75                "/xyz/openbmc_project/sensors/fan_tach/fan1_1": {
76                    "Functional": true,
77                    "Value": {}
78                }
79            }]
80        }
81    }
82}
83```
84
85Input JSON set of entries(input.json):
86```
87{
88    "data": {
89        "/xyz/openbmc_project/sensors/fan_tach/fan0_0": {
90            "CriticalAlarmHigh": false,
91            "CriticalAlarmLow": true,
92            "CriticalHigh": 12076,
93            "CriticalLow": 2974,
94            "Functional": true,
95            "MaxValue": 0,
96            "MinValue": 0,
97            "Scale": 0,
98            "Target": 10500,
99            "Unit": "xyz.openbmc_project.Sensor.Value.Unit.RPMS",
100            "Value": 0
101        },
102        "/xyz/openbmc_project/sensors/fan_tach/fan0_0/chassis": {
103            "endpoints": [
104                "/xyz/openbmc_project/inventory/system/chassis"
105            ]
106        },
107        "/xyz/openbmc_project/sensors/fan_tach/fan0_0/inventory": {
108            "endpoints": [
109                "/xyz/openbmc_project/inventory/system/chassis/motherboard/fan0"
110            ]
111        },
112        "/xyz/openbmc_project/sensors/fan_tach/fan0_1": {
113            "CriticalAlarmHigh": false,
114            "CriticalAlarmLow": false,
115            "CriticalHigh": 12076,
116            "CriticalLow": 2974,
117            "Functional": true,
118            "MaxValue": 0,
119            "MinValue": 0,
120            "Scale": 0,
121            "Unit": "xyz.openbmc_project.Sensor.Value.Unit.RPMS",
122            "Value": 3393
123        },
124        "/xyz/openbmc_project/sensors/fan_tach/fan0_1/chassis": {
125            "endpoints": [
126                "/xyz/openbmc_project/inventory/system/chassis"
127            ]
128        },
129        "/xyz/openbmc_project/sensors/fan_tach/fan0_1/inventory": {
130            "endpoints": [
131                "/xyz/openbmc_project/inventory/system/chassis/motherboard/fan0"
132            ]
133        },
134        "/xyz/openbmc_project/sensors/fan_tach/fan1_0": {
135            "CriticalAlarmHigh": false,
136            "CriticalAlarmLow": true,
137            "CriticalHigh": 12076,
138            "CriticalLow": 2974,
139            "Functional": true,
140            "MaxValue": 0,
141            "MinValue": 0,
142            "Scale": 0,
143            "Target": 10500,
144            "Unit": "xyz.openbmc_project.Sensor.Value.Unit.RPMS",
145            "Value": 0
146        },
147        "/xyz/openbmc_project/sensors/fan_tach/fan1_0/chassis": {
148            "endpoints": [
149                "/xyz/openbmc_project/inventory/system/chassis"
150            ]
151        },
152        "/xyz/openbmc_project/sensors/fan_tach/fan1_0/inventory": {
153            "endpoints": [
154                "/xyz/openbmc_project/inventory/system/chassis/motherboard/fan1"
155            ]
156        },
157        "/xyz/openbmc_project/sensors/fan_tach/fan1_1": {
158            "CriticalAlarmHigh": false,
159            "CriticalAlarmLow": false,
160            "CriticalHigh": 12076,
161            "CriticalLow": 2974,
162            "Functional": true,
163            "MaxValue": 0,
164            "MinValue": 0,
165            "Scale": 0,
166            "Unit": "xyz.openbmc_project.Sensor.Value.Unit.RPMS",
167            "Value": 3409
168        },
169        "/xyz/openbmc_project/sensors/fan_tach/fan1_1/chassis": {
170            "endpoints": [
171                "/xyz/openbmc_project/inventory/system/chassis"
172            ]
173        },
174        "/xyz/openbmc_project/sensors/fan_tach/fan1_1/inventory": {
175            "endpoints": [
176                "/xyz/openbmc_project/inventory/system/chassis/motherboard/fan1"
177            ]
178        },
179        "/xyz/openbmc_project/sensors/power/ps0_input_power": {
180            "CriticalAlarmHigh": false,
181            "CriticalAlarmLow": true,
182            "CriticalHigh": 2500000000,
183            "CriticalLow": 0,
184            "Functional": true,
185            "MaxValue": 0,
186            "MinValue": 0,
187            "Scale": -6,
188            "Unit": "xyz.openbmc_project.Sensor.Value.Unit.Watts",
189            "Value": 0,
190            "WarningAlarmHigh": false,
191            "WarningAlarmLow": true,
192            "WarningHigh": 2350000000,
193            "WarningLow": 0
194        },
195        "/xyz/openbmc_project/sensors/power/ps0_input_power/chassis": {
196            "endpoints": [
197                "/xyz/openbmc_project/inventory/system/chassis"
198            ]
199        },
200        "/xyz/openbmc_project/sensors/power/ps0_input_power/inventory": {
201            "endpoints": [
202                "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"
203            ]
204        },
205        "/xyz/openbmc_project/sensors/power/ps1_input_power": {
206            "CriticalAlarmHigh": false,
207            "CriticalAlarmLow": false,
208            "CriticalHigh": 2500000000,
209            "CriticalLow": 0,
210            "Functional": true,
211            "MaxValue": 0,
212            "MinValue": 0,
213            "Scale": -6,
214            "Unit": "xyz.openbmc_project.Sensor.Value.Unit.Watts",
215            "Value": 18000000,
216            "WarningAlarmHigh": false,
217            "WarningAlarmLow": false,
218            "WarningHigh": 2350000000,
219            "WarningLow": 0
220        },
221        "/xyz/openbmc_project/sensors/power/ps1_input_power/chassis": {
222            "endpoints": [
223                "/xyz/openbmc_project/inventory/system/chassis"
224            ]
225        },
226        "/xyz/openbmc_project/sensors/power/ps1_input_power/inventory": {
227            "endpoints": [
228                "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1"
229            ]
230        },
231        "/xyz/openbmc_project/sensors/temperature/ambient": {
232            "CriticalAlarmHigh": false,
233            "CriticalAlarmLow": false,
234            "CriticalHigh": 35000,
235            "CriticalLow": 0,
236            "Functional": true,
237            "MaxValue": 0,
238            "MinValue": 0,
239            "Scale": -3,
240            "Unit": "xyz.openbmc_project.Sensor.Value.Unit.DegreesC",
241            "Value": 22420,
242            "WarningAlarmHigh": false,
243            "WarningAlarmLow": false,
244            "WarningHigh": 25000,
245            "WarningLow": 0
246        }
247    },
248    "message": "200 OK",
249    "status": "ok"
250}
251```
252
253Filter JSON set of entries(filter.json):
254```
255{
256    "data": {
257        "/xyz/openbmc_project/inventory/system": {
258            "AssetTag": "",
259            "BuildDate": "",
260            "Cached": false,
261            "FieldReplaceable": false,
262            "Manufacturer": "",
263            "Model": "8335-GTA        ",
264            "PartNumber": "",
265            "Present": true,
266            "PrettyName": "",
267            "SerialNumber": "1234567         "
268        },
269        "/xyz/openbmc_project/inventory/system/chassis": {
270            "AirCooled": true,
271            "Type": "RackMount",
272            "WaterCooled": false
273        },
274        "/xyz/openbmc_project/inventory/system/chassis/activation": {
275            "endpoints": [
276                "/xyz/openbmc_project/software/224cd310"
277            ]
278        },
279        "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0": {
280            "BuildDate": "1996-01-01 - 00:00:00",
281            "Cached": false,
282            "FieldReplaceable": true,
283            "Functional": true,
284            "Manufacturer": "IBM",
285            "Model": "",
286            "PartNumber": "02CY211",
287            "Present": true,
288            "PrettyName": "PROCESSOR MODULE",
289            "SerialNumber": "YA1934302447",
290            "Version": "22"
291        },
292        "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core0": {
293            "Associations": [
294                [
295                    "sensors",
296                    "inventory",
297                    "/xyz/openbmc_project/sensors/temperature/p0_core0_temp"
298                ]
299            ],
300            "Functional": true,
301            "Present": true,
302            "PrettyName": ""
303        },
304        "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core1": {
305            "Associations": [
306                [
307                    "sensors",
308                    "inventory",
309                    "/xyz/openbmc_project/sensors/temperature/p0_core1_temp"
310                ]
311            ],
312            "Functional": true,
313            "Present": true,
314            "PrettyName": ""
315        }
316    },
317    "message": "200 OK",
318    "status": "ok"
319}
320```
321
322Invoke the tool(with everything expected found):
323```
324> expectedJsonChecker.py witherspoon expected.json input.json -f filter.json
325```
326Invoke the tool(with modified fan1_0 `Functional` property to `False`):
327```
328> expectedJsonChecker.py witherspoon expected.json input.json -f filter.json
329NOT FOUND:
330/xyz/openbmc_project/sensors/fan_tach/fan1_0: {u'Functional': False}
331```
332