pytest-libiio 0.0.22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pytest_libiio/__init__.py +3 -0
- pytest_libiio/coverage.py +192 -0
- pytest_libiio/meta.py +255 -0
- pytest_libiio/mkpatch.py +113 -0
- pytest_libiio/plugin.py +696 -0
- pytest_libiio/resources/adi_hardware_map.yml +217 -0
- pytest_libiio/resources/devices/ad4020.xml +0 -0
- pytest_libiio/resources/devices/ad9081.xml +1 -0
- pytest_libiio/resources/devices/ad9081_tdd.xml +1 -0
- pytest_libiio/resources/devices/ad9172.xml +1 -0
- pytest_libiio/resources/devices/ad9265.xml +1 -0
- pytest_libiio/resources/devices/ad9371.xml +1 -0
- pytest_libiio/resources/devices/ad9375.xml +1 -0
- pytest_libiio/resources/devices/ad9434.xml +1 -0
- pytest_libiio/resources/devices/adrv9002.xml +18 -0
- pytest_libiio/resources/devices/adrv9002_singledma.xml +926 -0
- pytest_libiio/resources/devices/adrv9002_splitdma.xml +1046 -0
- pytest_libiio/resources/devices/adrv9361-z7035.xml +3 -0
- pytest_libiio/resources/devices/adrv9364-z7020.xml +4 -0
- pytest_libiio/resources/devices/adt7420.xml +1 -0
- pytest_libiio/resources/devices/adxl355.xml +2 -0
- pytest_libiio/resources/devices/cn0511.xml +1 -0
- pytest_libiio/resources/devices/cn0540.xml +1 -0
- pytest_libiio/resources/devices/daq2.xml +2 -0
- pytest_libiio/resources/devices/daq3.xml +2 -0
- pytest_libiio/resources/devices/fmcomms11.xml +1 -0
- pytest_libiio/resources/devices/fmcomms2-3.xml +3 -0
- pytest_libiio/resources/devices/fmcomms4.xml +4 -0
- pytest_libiio/resources/devices/fmcomms5.xml +5 -0
- pytest_libiio/resources/devices/ltc2387.xml +1 -0
- pytest_libiio/resources/devices/pluto.xml +4 -0
- pytest_libiio/tools.py +20 -0
- pytest_libiio-0.0.22.dist-info/METADATA +159 -0
- pytest_libiio-0.0.22.dist-info/RECORD +38 -0
- pytest_libiio-0.0.22.dist-info/WHEEL +5 -0
- pytest_libiio-0.0.22.dist-info/entry_points.txt +5 -0
- pytest_libiio-0.0.22.dist-info/licenses/LICENSE +28 -0
- pytest_libiio-0.0.22.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Coverage tracking for iio attributes using monkey patching."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
from pprint import pprint
|
|
6
|
+
|
|
7
|
+
import iio
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MultiContextTracker:
|
|
11
|
+
"""Class to track coverage across multiple DUTs."""
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.trackers = {}
|
|
15
|
+
self.track_debug_props = False
|
|
16
|
+
self.results_folder = "iio_coverage_results"
|
|
17
|
+
|
|
18
|
+
def do_monkey_patch(self):
|
|
19
|
+
"""Apply monkey patch to iio.py."""
|
|
20
|
+
from . import mkpatch
|
|
21
|
+
from .mkpatch import reset_coverage_tracker
|
|
22
|
+
|
|
23
|
+
reset_coverage_tracker()
|
|
24
|
+
|
|
25
|
+
def add_instance(self, name, uri):
|
|
26
|
+
"""Add a new context to track.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
name (str): Name of the context. Just a label, not used in iio.
|
|
30
|
+
uri (str): URI of the context.
|
|
31
|
+
"""
|
|
32
|
+
if uri not in self.trackers:
|
|
33
|
+
self.trackers[name] = CoverageTracker(name, uri, self.track_debug_props)
|
|
34
|
+
|
|
35
|
+
def set_tracker(self, name):
|
|
36
|
+
from .mkpatch import set_coverage_tracker
|
|
37
|
+
|
|
38
|
+
if name not in self.trackers:
|
|
39
|
+
raise ValueError(f"{name} not tracked.")
|
|
40
|
+
|
|
41
|
+
set_coverage_tracker(tracker=self.trackers[name])
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class CoverageTracker:
|
|
45
|
+
"""Class to track coverage of iio attributes."""
|
|
46
|
+
|
|
47
|
+
def __init__(self, name, uri, track_debug_props=False, results_folder=None):
|
|
48
|
+
self.name = name
|
|
49
|
+
self.context_attr_reads_writes = {}
|
|
50
|
+
self.device_attr_reads_writes = {}
|
|
51
|
+
self.channel_attr_reads_writes = {}
|
|
52
|
+
self.debug_attr_reads_writes = {}
|
|
53
|
+
self.uri = uri
|
|
54
|
+
self.ctx = iio.Context(uri)
|
|
55
|
+
self.track_debug_props = track_debug_props
|
|
56
|
+
self.results_folder = results_folder or "iio_coverage_results"
|
|
57
|
+
self.build_context_map()
|
|
58
|
+
|
|
59
|
+
def reset(self):
|
|
60
|
+
"""Reset the coverage tracker."""
|
|
61
|
+
self.context_attr_reads_writes.clear()
|
|
62
|
+
self.device_attr_reads_writes.clear()
|
|
63
|
+
self.channel_attr_reads_writes.clear()
|
|
64
|
+
self.debug_attr_reads_writes.clear()
|
|
65
|
+
|
|
66
|
+
def build_context_map(self):
|
|
67
|
+
"""Build a map of context attributes."""
|
|
68
|
+
self.context_attr_reads_writes = {attr: 0 for attr in self.ctx.attrs}
|
|
69
|
+
for dev in self.ctx.devices:
|
|
70
|
+
self.device_attr_reads_writes[dev.name] = {attr: 0 for attr in dev.attrs}
|
|
71
|
+
self.channel_attr_reads_writes[dev.name] = {
|
|
72
|
+
chn.id: {attr: 0 for attr in chn.attrs} for chn in dev.channels
|
|
73
|
+
}
|
|
74
|
+
if self.track_debug_props:
|
|
75
|
+
self.debug_attr_reads_writes[dev.name] = {
|
|
76
|
+
attr: 0 for attr in dev.debug_attrs
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
def export(self):
|
|
80
|
+
"""Export raw coverage data."""
|
|
81
|
+
out = {
|
|
82
|
+
"context_attr_reads_writes": self.context_attr_reads_writes,
|
|
83
|
+
"device_attr_reads_writes": self.device_attr_reads_writes,
|
|
84
|
+
"channel_attr_reads_writes": self.channel_attr_reads_writes,
|
|
85
|
+
}
|
|
86
|
+
if self.track_debug_props:
|
|
87
|
+
out["debug_attr_reads_writes"] = self.debug_attr_reads_writes
|
|
88
|
+
return out
|
|
89
|
+
|
|
90
|
+
def export_to_file(self, filename=None):
|
|
91
|
+
"""Export coverage data to a file.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
filename (str, optional): Name of the file to save the coverage data.
|
|
95
|
+
If None, defaults to "{self.name}_coverage.json".
|
|
96
|
+
"""
|
|
97
|
+
if filename is None:
|
|
98
|
+
filename = f"{self.name}_coverage.json"
|
|
99
|
+
if not os.path.exists(self.results_folder):
|
|
100
|
+
os.makedirs(self.results_folder)
|
|
101
|
+
filename = os.path.join(os.getcwd(), self.results_folder, filename)
|
|
102
|
+
with open(filename, "w") as f:
|
|
103
|
+
json.dump(self.export(), f, indent=4)
|
|
104
|
+
print(f"Coverage data exported to {filename}")
|
|
105
|
+
|
|
106
|
+
def print_context_map(self):
|
|
107
|
+
print("Context Attribute Reads:")
|
|
108
|
+
pprint(self.context_attr_reads_writes)
|
|
109
|
+
print("Device Attribute Reads:")
|
|
110
|
+
pprint(self.device_attr_reads_writes)
|
|
111
|
+
print("Channel Attribute Reads:")
|
|
112
|
+
pprint(self.channel_attr_reads_writes)
|
|
113
|
+
if self.track_debug_props:
|
|
114
|
+
print("Debug Attribute Reads:")
|
|
115
|
+
pprint(self.debug_attr_reads_writes)
|
|
116
|
+
|
|
117
|
+
def calculate_coverage(self):
|
|
118
|
+
"""Calculate coverage based on attribute reads and writes."""
|
|
119
|
+
|
|
120
|
+
total_context_reads_writes = sum(self.context_attr_reads_writes.values())
|
|
121
|
+
total_context_attributes = len(self.context_attr_reads_writes)
|
|
122
|
+
|
|
123
|
+
total_device_reads_writes = sum(
|
|
124
|
+
sum(device.values()) for device in self.device_attr_reads_writes.values()
|
|
125
|
+
)
|
|
126
|
+
total_device_attributes = sum(
|
|
127
|
+
len(device) for device in self.device_attr_reads_writes.values()
|
|
128
|
+
)
|
|
129
|
+
if self.track_debug_props:
|
|
130
|
+
total_debug_reads_writes = sum(
|
|
131
|
+
self.debug_attr_reads_writes[dev].values()
|
|
132
|
+
for dev in self.debug_attr_reads_writes
|
|
133
|
+
)
|
|
134
|
+
total_device_attributes = sum(
|
|
135
|
+
len(self.debug_attr_reads_writes[dev])
|
|
136
|
+
for dev in self.debug_attr_reads_writes
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
total_channel_reads_writes = 0
|
|
140
|
+
total_channel_attributes = 0
|
|
141
|
+
for device in self.channel_attr_reads_writes:
|
|
142
|
+
for channel in self.channel_attr_reads_writes[device]:
|
|
143
|
+
total_channel_reads_writes += sum(
|
|
144
|
+
self.channel_attr_reads_writes[device][channel].values()
|
|
145
|
+
)
|
|
146
|
+
total_channel_attributes += len(
|
|
147
|
+
self.channel_attr_reads_writes[device][channel]
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
out = {
|
|
151
|
+
"context_coverage": (
|
|
152
|
+
total_context_reads_writes / total_context_attributes
|
|
153
|
+
if total_context_attributes
|
|
154
|
+
else 0
|
|
155
|
+
),
|
|
156
|
+
"device_coverage": (
|
|
157
|
+
total_device_reads_writes / total_device_attributes
|
|
158
|
+
if total_device_attributes
|
|
159
|
+
else 0
|
|
160
|
+
),
|
|
161
|
+
"channel_coverage": (
|
|
162
|
+
total_channel_reads_writes / total_channel_attributes
|
|
163
|
+
if total_channel_attributes
|
|
164
|
+
else 0
|
|
165
|
+
),
|
|
166
|
+
"total_coverage": (
|
|
167
|
+
total_context_reads_writes
|
|
168
|
+
+ total_device_reads_writes
|
|
169
|
+
+ total_channel_reads_writes
|
|
170
|
+
)
|
|
171
|
+
/ (
|
|
172
|
+
total_context_attributes
|
|
173
|
+
+ total_device_attributes
|
|
174
|
+
+ total_channel_attributes
|
|
175
|
+
),
|
|
176
|
+
"total_context_reads_writes": total_context_reads_writes,
|
|
177
|
+
"total_device_reads_writes": total_device_reads_writes,
|
|
178
|
+
"total_channel_reads_writes": total_channel_reads_writes,
|
|
179
|
+
"total_context_attributes": total_context_attributes,
|
|
180
|
+
"total_device_attributes": total_device_attributes,
|
|
181
|
+
"total_channel_attributes": total_channel_attributes,
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if self.track_debug_props:
|
|
185
|
+
out["total_debug_reads_writes"] = total_debug_reads_writes
|
|
186
|
+
out["total_debug_attributes"] = total_device_attributes
|
|
187
|
+
out["debug_coverage"] = (
|
|
188
|
+
total_debug_reads_writes / total_device_attributes
|
|
189
|
+
if total_device_attributes
|
|
190
|
+
else 0
|
|
191
|
+
)
|
|
192
|
+
return out
|
pytest_libiio/meta.py
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"""This is a set of function to help extract metadata from tests and hardware"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
import xml.etree.ElementTree as ET
|
|
6
|
+
from io import BytesIO, StringIO
|
|
7
|
+
from pprint import pprint
|
|
8
|
+
|
|
9
|
+
import iio
|
|
10
|
+
|
|
11
|
+
import lxml.etree as etree
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
import paramiko
|
|
15
|
+
|
|
16
|
+
useSSH = True
|
|
17
|
+
except ImportError:
|
|
18
|
+
useSSH = False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def __get_value_from_hw(
|
|
22
|
+
ctx, attrib, ptype, attr_name, dev_name=None, ch_name=None, is_output=False
|
|
23
|
+
):
|
|
24
|
+
if "value" in attrib:
|
|
25
|
+
value = attrib["value"]
|
|
26
|
+
else:
|
|
27
|
+
if ptype == "context":
|
|
28
|
+
value = ctx.attrs[attr_name].value
|
|
29
|
+
elif ptype == "device":
|
|
30
|
+
dev = ctx.find_device(str(dev_name))
|
|
31
|
+
try:
|
|
32
|
+
value = dev.attrs[attr_name].value
|
|
33
|
+
except OSError:
|
|
34
|
+
value = "ERROR"
|
|
35
|
+
elif ptype == "channel":
|
|
36
|
+
dev = ctx.find_device(str(dev_name))
|
|
37
|
+
ch = dev.find_channel(str(ch_name), is_output)
|
|
38
|
+
if hasattr(ch, "attrs") and attr_name in ch.attrs:
|
|
39
|
+
try:
|
|
40
|
+
value = ch.attrs[attr_name].value
|
|
41
|
+
except OSError:
|
|
42
|
+
value = "ERROR"
|
|
43
|
+
else:
|
|
44
|
+
value = "NO ATTRS FOR CHANNEL"
|
|
45
|
+
elif ptype == "debug":
|
|
46
|
+
dev = ctx.find_device(str(dev_name))
|
|
47
|
+
try:
|
|
48
|
+
value = dev.debug_attrs[attr_name].value
|
|
49
|
+
except OSError:
|
|
50
|
+
value = "ERROR"
|
|
51
|
+
elif ptype == "buffer":
|
|
52
|
+
dev = ctx.find_device(str(dev_name))
|
|
53
|
+
try:
|
|
54
|
+
value = dev.buffer_attrs[attr_name].value
|
|
55
|
+
except OSError:
|
|
56
|
+
value = "ERROR"
|
|
57
|
+
else:
|
|
58
|
+
raise Exception("Unknown property type")
|
|
59
|
+
|
|
60
|
+
return value
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def __get_name_id(item):
|
|
64
|
+
return item.attrib["name"] if "name" in item.attrib else item.attrib["id"]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def dprint(*args, **kwargs):
|
|
68
|
+
"""Debug print"""
|
|
69
|
+
if os.environ.get("DEBUG"):
|
|
70
|
+
print(*args, **kwargs)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_emulated_context(ctx: iio.Context):
|
|
74
|
+
cxml = ctx.xml
|
|
75
|
+
cxml = str(cxml)
|
|
76
|
+
|
|
77
|
+
# Convert string to xml
|
|
78
|
+
root = ET.fromstring(cxml)
|
|
79
|
+
|
|
80
|
+
context_fields = list(root.attrib.keys())
|
|
81
|
+
|
|
82
|
+
# loop through items
|
|
83
|
+
for item in root:
|
|
84
|
+
if item.tag == "context-attribute":
|
|
85
|
+
dprint("Context-attribute---")
|
|
86
|
+
attr_name_id = __get_name_id(item)
|
|
87
|
+
value = __get_value_from_hw(ctx, item.attrib, "context", attr_name_id)
|
|
88
|
+
dprint("CONTEXT", attr_name_id, value)
|
|
89
|
+
item.attrib["value"] = value
|
|
90
|
+
elif item.tag == "device":
|
|
91
|
+
dprint("Device---")
|
|
92
|
+
device_name_id = __get_name_id(item)
|
|
93
|
+
# Devices
|
|
94
|
+
for sitem in item:
|
|
95
|
+
attr_name_id = __get_name_id(sitem)
|
|
96
|
+
# Device attributes
|
|
97
|
+
if sitem.tag == "attribute":
|
|
98
|
+
value = __get_value_from_hw(
|
|
99
|
+
ctx, sitem.attrib, "device", attr_name_id, device_name_id
|
|
100
|
+
)
|
|
101
|
+
dprint("DEVICE", device_name_id, attr_name_id, value)
|
|
102
|
+
sitem.attrib["value"] = value
|
|
103
|
+
# Channel attributes
|
|
104
|
+
elif sitem.tag == "channel":
|
|
105
|
+
channel_name_id = attr_name_id
|
|
106
|
+
if sitem.attrib["type"] == "output":
|
|
107
|
+
is_output = True
|
|
108
|
+
elif sitem.attrib["type"] == "input":
|
|
109
|
+
is_output = False
|
|
110
|
+
else:
|
|
111
|
+
raise Exception("Unknown channel type")
|
|
112
|
+
for ssitem in sitem:
|
|
113
|
+
if ssitem.tag == "scan-element":
|
|
114
|
+
continue # FIXME
|
|
115
|
+
channel_attr_name_id = __get_name_id(ssitem)
|
|
116
|
+
value = __get_value_from_hw(
|
|
117
|
+
ctx,
|
|
118
|
+
ssitem.attrib,
|
|
119
|
+
"channel",
|
|
120
|
+
channel_attr_name_id,
|
|
121
|
+
device_name_id,
|
|
122
|
+
channel_name_id,
|
|
123
|
+
is_output,
|
|
124
|
+
)
|
|
125
|
+
dprint(
|
|
126
|
+
"CHANNEL",
|
|
127
|
+
device_name_id,
|
|
128
|
+
channel_name_id,
|
|
129
|
+
is_output,
|
|
130
|
+
channel_attr_name_id,
|
|
131
|
+
value,
|
|
132
|
+
)
|
|
133
|
+
ssitem.attrib["value"] = value
|
|
134
|
+
|
|
135
|
+
elif sitem.tag == "debug-attribute":
|
|
136
|
+
value = __get_value_from_hw(
|
|
137
|
+
ctx, sitem.attrib, "debug", attr_name_id, device_name_id
|
|
138
|
+
)
|
|
139
|
+
dprint("DEBUG", device_name_id, attr_name_id, value)
|
|
140
|
+
sitem.attrib["value"] = value
|
|
141
|
+
|
|
142
|
+
elif sitem.tag == "buffer-attribute":
|
|
143
|
+
value = __get_value_from_hw(
|
|
144
|
+
ctx, sitem.attrib, "buffer", attr_name_id, device_name_id
|
|
145
|
+
)
|
|
146
|
+
dprint("BUFFER", device_name_id, attr_name_id, value)
|
|
147
|
+
sitem.attrib["value"] = value
|
|
148
|
+
else:
|
|
149
|
+
raise Exception("Unknown device item")
|
|
150
|
+
else:
|
|
151
|
+
raise Exception("Unknown item")
|
|
152
|
+
|
|
153
|
+
# Update context ATTLIST of DOCTYPE to include all context fields
|
|
154
|
+
context_fields += ["description"]
|
|
155
|
+
context_fields = list(set(context_fields))
|
|
156
|
+
template = "<!ATTLIST context "
|
|
157
|
+
context_fields_list = [
|
|
158
|
+
f"{field.replace(',','').replace(' ','_')} CDATA #IMPLIED "
|
|
159
|
+
for field in context_fields
|
|
160
|
+
]
|
|
161
|
+
full = template + "".join(context_fields_list)
|
|
162
|
+
full = f"{full[:-1]}>"
|
|
163
|
+
|
|
164
|
+
doctype = f"<!DOCTYPE context [\n\
|
|
165
|
+
<!ELEMENT context (device | context-attribute)*>\n\
|
|
166
|
+
<!ELEMENT context-attribute EMPTY>\n\
|
|
167
|
+
<!ELEMENT device (channel | attribute | debug-attribute | buffer-attribute)*>\n\
|
|
168
|
+
<!ELEMENT channel (scan-element?, attribute*)>\n\
|
|
169
|
+
<!ELEMENT attribute EMPTY><!ELEMENT scan-element EMPTY>\n\
|
|
170
|
+
<!ELEMENT debug-attribute EMPTY>\n\
|
|
171
|
+
<!ELEMENT buffer-attribute EMPTY>\n\
|
|
172
|
+
{full}\n\
|
|
173
|
+
<!ATTLIST context-attribute name CDATA #REQUIRED value CDATA #REQUIRED>\n\
|
|
174
|
+
<!ATTLIST device id CDATA #REQUIRED name CDATA #IMPLIED>\n\
|
|
175
|
+
<!ATTLIST channel id CDATA #REQUIRED type (input|output) #REQUIRED name CDATA #IMPLIED>\n\
|
|
176
|
+
<!ATTLIST scan-element index CDATA #REQUIRED format CDATA #REQUIRED scale CDATA #IMPLIED>\n\
|
|
177
|
+
<!ATTLIST attribute name CDATA #REQUIRED filename CDATA #IMPLIED value CDATA #IMPLIED>\n\
|
|
178
|
+
<!ATTLIST debug-attribute name CDATA #REQUIRED value CDATA #IMPLIED>\n\
|
|
179
|
+
<!ATTLIST buffer-attribute name CDATA #REQUIRED value CDATA #IMPLIED>\n\
|
|
180
|
+
]>"
|
|
181
|
+
|
|
182
|
+
xml_str = ET.tostring(root, encoding="unicode")
|
|
183
|
+
|
|
184
|
+
tree = etree.parse(StringIO(xml_str))
|
|
185
|
+
xml_str = etree.tostring(
|
|
186
|
+
tree, pretty_print=True, xml_declaration=True, doctype=doctype, encoding="utf-8"
|
|
187
|
+
)
|
|
188
|
+
xml_str = str(xml_str, "utf-8") # type: ignore
|
|
189
|
+
return xml_str
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def get_ssh_session(ctx: iio.Context):
|
|
193
|
+
"""Get ssh session"""
|
|
194
|
+
uri = ctx.attrs["uri"].split(":")
|
|
195
|
+
if not useSSH:
|
|
196
|
+
print("Paramiko is not installed, cannot use SSH")
|
|
197
|
+
return None
|
|
198
|
+
if uri[0] == "ip":
|
|
199
|
+
print(f"Starting SSH session for uri: {ctx.attrs['uri']}")
|
|
200
|
+
ip = uri[1]
|
|
201
|
+
ssh = paramiko.SSHClient()
|
|
202
|
+
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
|
|
203
|
+
ssh.connect(ip, username="root", password="analog")
|
|
204
|
+
return ssh
|
|
205
|
+
else:
|
|
206
|
+
print(f"URI: {ctx.attrs['uri']} is not supported for SSH telemetry")
|
|
207
|
+
return None
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def get_hardware_info(ctx: iio.Context, ssh=None):
|
|
211
|
+
"""Get hardware information from the context"""
|
|
212
|
+
local = {}
|
|
213
|
+
remote = {}
|
|
214
|
+
|
|
215
|
+
local["libiio"] = iio.version
|
|
216
|
+
|
|
217
|
+
# Get context xml and values from HW
|
|
218
|
+
remote["iio_context"] = get_emulated_context(ctx)
|
|
219
|
+
|
|
220
|
+
# Get telemetry data from remote linux system
|
|
221
|
+
uri = ctx.attrs["uri"].split(":")
|
|
222
|
+
if uri[0] == "ip" and ssh is not None:
|
|
223
|
+
stdin, stdout, stderr = ssh.exec_command("dmesg")
|
|
224
|
+
remote["dmesg"] = stdout.read().decode()
|
|
225
|
+
stdin, stdout, stderr = ssh.exec_command("uname -a")
|
|
226
|
+
remote["uname"] = stdout.read().decode()
|
|
227
|
+
stdin, stdout, stderr = ssh.exec_command("cat /proc/cpuinfo")
|
|
228
|
+
remote["cpuinfo"] = stdout.read().decode()
|
|
229
|
+
stdin, stdout, stderr = ssh.exec_command("cat /proc/meminfo")
|
|
230
|
+
remote["meminfo"] = stdout.read().decode()
|
|
231
|
+
stdin, stdout, stderr = ssh.exec_command("cat /proc/version")
|
|
232
|
+
remote["version"] = stdout.read().decode()
|
|
233
|
+
stdin, stdout, stderr = ssh.exec_command("cat /etc/os-release")
|
|
234
|
+
remote["os-release"] = stdout.read().decode()
|
|
235
|
+
stdin, stdout, stderr = ssh.exec_command("df -h")
|
|
236
|
+
remote["df"] = stdout.read().decode()
|
|
237
|
+
stdin, stdout, stderr = ssh.exec_command(
|
|
238
|
+
'python -c "import iio; print(iio.version)"'
|
|
239
|
+
)
|
|
240
|
+
remote["libiio"] = stdout.read().decode()
|
|
241
|
+
stdin, stdout, stderr = ssh.exec_command("iio_info")
|
|
242
|
+
remote["iio_info"] = stdout.read().decode()
|
|
243
|
+
# ssh.close()
|
|
244
|
+
|
|
245
|
+
metadata = {}
|
|
246
|
+
metadata["local"] = local
|
|
247
|
+
metadata["remote"] = remote
|
|
248
|
+
|
|
249
|
+
return metadata
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
if __name__ == "__main__":
|
|
253
|
+
ctx = iio.Context("ip:analog.local")
|
|
254
|
+
# root = get_hardware_info(ctx)
|
|
255
|
+
root = get_emulated_context(ctx)
|
pytest_libiio/mkpatch.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from pprint import pprint
|
|
3
|
+
|
|
4
|
+
import iio
|
|
5
|
+
from iio import ChannelAttr as _Attr
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
coverage_tracker = None
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _check_tracker():
|
|
13
|
+
"""Check if the coverage tracker is set."""
|
|
14
|
+
global coverage_tracker # noqa: F824
|
|
15
|
+
if coverage_tracker is None:
|
|
16
|
+
raise RuntimeError(
|
|
17
|
+
"Coverage tracker is not set. Call set_coverage_tracker first."
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _read(self):
|
|
22
|
+
"""MP Read method to capture attribute reads"""
|
|
23
|
+
attr_name = self.name
|
|
24
|
+
if self._channel:
|
|
25
|
+
name_raw = iio._c_get_id(self._channel)
|
|
26
|
+
channel_name = name_raw.decode("ascii") if name_raw is not None else None
|
|
27
|
+
dev_ptr = iio._channel_get_device(self._channel)
|
|
28
|
+
name_raw = iio._d_get_name(dev_ptr)
|
|
29
|
+
device_name = name_raw.decode("ascii") if name_raw is not None else None
|
|
30
|
+
else:
|
|
31
|
+
channel_name = None
|
|
32
|
+
device_name = self._name
|
|
33
|
+
|
|
34
|
+
_check_tracker()
|
|
35
|
+
|
|
36
|
+
global coverage_tracker # noqa: F824
|
|
37
|
+
if channel_name and device_name:
|
|
38
|
+
coverage_tracker.channel_attr_reads_writes[device_name][channel_name][
|
|
39
|
+
attr_name
|
|
40
|
+
] += 1
|
|
41
|
+
elif device_name:
|
|
42
|
+
coverage_tracker.device_attr_reads_writes[device_name][attr_name] += 1
|
|
43
|
+
else:
|
|
44
|
+
coverage_tracker.context_attr_reads_writes[attr_name] += 1
|
|
45
|
+
|
|
46
|
+
logger.debug(
|
|
47
|
+
f"Reading attribute: {attr_name}, Channel: {channel_name}, Device: {device_name}"
|
|
48
|
+
)
|
|
49
|
+
return self._read_org()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _write(self, value):
|
|
53
|
+
"""MP Write method to capture attribute writes"""
|
|
54
|
+
attr_name = self.name
|
|
55
|
+
if self._channel:
|
|
56
|
+
name_raw = iio._c_get_id(self._channel)
|
|
57
|
+
channel_name = name_raw.decode("ascii") if name_raw is not None else None
|
|
58
|
+
dev_ptr = iio._channel_get_device(self._channel)
|
|
59
|
+
name_raw = iio._d_get_name(dev_ptr)
|
|
60
|
+
device_name = name_raw.decode("ascii") if name_raw is not None else None
|
|
61
|
+
else:
|
|
62
|
+
channel_name = None
|
|
63
|
+
device_name = self._name
|
|
64
|
+
|
|
65
|
+
_check_tracker()
|
|
66
|
+
|
|
67
|
+
global coverage_tracker # noqa: F824
|
|
68
|
+
if channel_name and device_name:
|
|
69
|
+
coverage_tracker.channel_attr_reads_writes[device_name][channel_name][
|
|
70
|
+
attr_name
|
|
71
|
+
] += 1
|
|
72
|
+
elif device_name:
|
|
73
|
+
coverage_tracker.device_attr_reads_writes[device_name][attr_name] += 1
|
|
74
|
+
else:
|
|
75
|
+
coverage_tracker.context_attr_reads_writes[attr_name] += 1
|
|
76
|
+
|
|
77
|
+
logger.debug(
|
|
78
|
+
f"Writing attribute: {attr_name}, Channel: {channel_name}, Device: {device_name}, Value: {value}"
|
|
79
|
+
)
|
|
80
|
+
self._write_org(value)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
_Attr._read_org = _Attr._read
|
|
84
|
+
_Attr._read = _read
|
|
85
|
+
|
|
86
|
+
_Attr._write_org = _Attr._write
|
|
87
|
+
_Attr._write = _write
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def set_coverage_tracker(tracker):
|
|
91
|
+
"""Set up the coverage tracker for iio attributes."""
|
|
92
|
+
global coverage_tracker
|
|
93
|
+
|
|
94
|
+
coverage_tracker = tracker
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def reset_coverage_tracker():
|
|
98
|
+
"""Reset the coverage tracker."""
|
|
99
|
+
global coverage_tracker
|
|
100
|
+
coverage_tracker = None
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def unset_monkey_patch():
|
|
104
|
+
"""Unset the monkey patch for iio attributes."""
|
|
105
|
+
global coverage_tracker
|
|
106
|
+
if coverage_tracker:
|
|
107
|
+
coverage_tracker = None
|
|
108
|
+
|
|
109
|
+
_Attr._read = _Attr._read_org
|
|
110
|
+
_Attr._write = _Attr._write_org
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
logger.debug("iio.py monkey patch applied")
|