1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-07-13 01:20:24 +02:00

Merge pull request #176 from kellyjonbrazil/dev

Dev v1.17.1
This commit is contained in:
Kelly Brazil
2021-10-30 14:02:25 -07:00
committed by GitHub
58 changed files with 13151 additions and 105 deletions

View File

@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: [3.6, 3.7, 3.8, 3.9, 3.10.0]
steps:
- uses: actions/checkout@v2

View File

@ -1,5 +1,13 @@
jc changelog
20211030 v1.17.1
- Fix file parser for gzip files
- Fix uname parser for cases where the 'processor' and/or 'hardware_platform' fields are missing on linux
- Fix uname parser on FreeBSD
- Add lsusb parser tested on linux
- Add CSV file streaming parser
- Add testing for Python 3.10.0
20210923 v1.17.0
- Note to Package Maintainers: please see note at 20210720 v1.16.0
- Add wrapping of warning and error messages

View File

@ -1917,6 +1917,128 @@ lsof | jc --lsof -p # or: jc -p lsof
}
]
```
### lsusb
```bash
lsusb -v | jc --lsusb -p # or: jc -p lsusb -v
```
```json
[
{
"bus": "002",
"device": "001",
"id": "1d6b:0001",
"description": "Linux Foundation 1.1 root hub",
"device_descriptor": {
"bLength": {
"value": "18"
},
"bDescriptorType": {
"value": "1"
},
"bcdUSB": {
"value": "1.10"
},
...
"bNumConfigurations": {
"value": "1"
},
"configuration_descriptor": {
"bLength": {
"value": "9"
},
...
"iConfiguration": {
"value": "0"
},
"bmAttributes": {
"value": "0xe0",
"attributes": [
"Self Powered",
"Remote Wakeup"
]
},
"MaxPower": {
"description": "0mA"
},
"interface_descriptors": [
{
"bLength": {
"value": "9"
},
...
"bInterfaceProtocol": {
"value": "0",
"description": "Full speed (or root) hub"
},
"iInterface": {
"value": "0"
},
"endpoint_descriptors": [
{
"bLength": {
"value": "7"
},
...
"bmAttributes": {
"value": "3",
"attributes": [
"Transfer Type Interrupt",
"Synch Type None",
"Usage Type Data"
]
},
"wMaxPacketSize": {
"value": "0x0002",
"description": "1x 2 bytes"
},
"bInterval": {
"value": "255"
}
}
]
}
]
}
},
"hub_descriptor": {
"bLength": {
"value": "9"
},
...
"wHubCharacteristic": {
"value": "0x000a",
"attributes": [
"No power switching (usb 1.0)",
"Per-port overcurrent protection"
]
},
...
"hub_port_status": {
"Port 1": {
"value": "0000.0103",
"attributes": [
"power",
"enable",
"connect"
]
},
"Port 2": {
"value": "0000.0103",
"attributes": [
"power",
"enable",
"connect"
]
}
}
},
"device_status": {
"value": "0x0001",
"description": "Self Powered"
}
}
]
```
### mount
```bash
mount | jc --mount -p # or: jc -p mount

View File

@ -115,6 +115,7 @@ The JSON output can be compact (default) or pretty formatted with the `-p` optio
- `--crontab` enables the `crontab` command and file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab))
- `--crontab-u` enables the `crontab` file parser with user support ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab_u))
- `--csv` enables the CSV file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/csv))
- `--csv-s` enables the CSV file streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/csv_s))
- `--date` enables the `date` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/date))
- `--df` enables the `df` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/df))
- `--dig` enables the `dig` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dig))
@ -147,6 +148,7 @@ The JSON output can be compact (default) or pretty formatted with the `-p` optio
- `--lsblk` enables the `lsblk` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk))
- `--lsmod` enables the `lsmod` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod))
- `--lsof` enables the `lsof` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof))
- `--lsusb` enables the `lsusb` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb))
- `--mount` enables the `mount` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/mount))
- `--netstat` enables the `netstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat))
- `--ntpq` enables the `ntpq -p` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq))

77
docs/parsers/csv_s.md Normal file
View File

@ -0,0 +1,77 @@
[Home](https://kellyjonbrazil.github.io/jc/)
# jc.parsers.csv_s
jc - JSON CLI output utility `csv` file streaming parser
> This streaming parser outputs JSON Lines
The `csv` streaming parser will attempt to automatically detect the delimiter character. If the delimiter cannot be detected it will default to comma. The first row of the file must be a header row.
Note: The first 100 rows are read into memory to enable delimiter detection, then the rest of the rows are loaded lazily.
Usage (cli):
$ cat file.csv | jc --csv-s
Usage (module):
import jc.parsers.csv_s
result = jc.parsers.csv_s.parse(csv_output)
Schema:
csv file converted to a Dictionary: https://docs.python.org/3/library/csv.html
{
"column_name1": string,
"column_name2": string
}
Examples:
$ cat homes.csv
"Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes"
142, 160, 28, 10, 5, 3, 60, 0.28, 3167
175, 180, 18, 8, 4, 1, 12, 0.43, 4033
129, 132, 13, 6, 3, 1, 41, 0.33, 1471
...
$ cat homes.csv | jc --csv-s
{"Sell":"142","List":"160","Living":"28","Rooms":"10","Beds":"5","Baths":"3","Age":"60","Acres":"0.28","Taxes":"3167"}
{"Sell":"175","List":"180","Living":"18","Rooms":"8","Beds":"4","Baths":"1","Age":"12","Acres":"0.43","Taxes":"4033"}
{"Sell":"129","List":"132","Living":"13","Rooms":"6","Beds":"3","Baths":"1","Age":"41","Acres":"0.33","Taxes":"1471"}
...
## info
```python
info()
```
Provides parser metadata (version, author, etc.)
## parse
```python
parse(data, raw=False, quiet=False, ignore_exceptions=False)
```
Main text parsing generator function. Returns an iterator object.
Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Yields:
Dictionary. Raw or processed structured data.
Returns:
Iterator object
## Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -87,4 +87,4 @@ Returns:
## Parser Information
Compatibility: linux, aix, freebsd, darwin
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)

288
docs/parsers/lsusb.md Normal file
View File

@ -0,0 +1,288 @@
[Home](https://kellyjonbrazil.github.io/jc/)
# jc.parsers.lsusb
jc - JSON CLI output utility `lsusb` command output parser
Supports the `-v` option or no options.
Usage (cli):
$ lsusb -v | jc --lsusb
or
$ jc lsusb -v
Usage (module):
import jc.parsers.lsusb
result = jc.parsers.lsusb.parse(lsusb_command_output)
Schema:
Note: <item> object keynames are assigned directly from the lsusb output.
If there are duplicate <item> names in a section, only the last one is converted.
[
{
"bus": string,
"device": string,
"id": string,
"description": string,
"device_descriptor": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
},
"configuration_descriptor": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
},
"interface_association": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"interface_descriptors": [
{
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
},
"cdc_header": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"cdc_call_management": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"cdc_acm": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"cdc_union": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"endpoint_descriptors": [
{
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
}
]
}
]
}
},
"hub_descriptor": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string,
]
},
"hub_port_status": {
"<item>": {
"value": string,
"attributes": [
string
]
}
}
},
"device_status": {
"value": string,
"description": string
}
}
]
Examples:
$ lsusb -v | jc --lsusb -p
[
{
"bus": "002",
"device": "001",
"id": "1d6b:0001",
"description": "Linux Foundation 1.1 root hub",
"device_descriptor": {
"bLength": {
"value": "18"
},
"bDescriptorType": {
"value": "1"
},
"bcdUSB": {
"value": "1.10"
},
...
"bNumConfigurations": {
"value": "1"
},
"configuration_descriptor": {
"bLength": {
"value": "9"
},
...
"iConfiguration": {
"value": "0"
},
"bmAttributes": {
"value": "0xe0",
"attributes": [
"Self Powered",
"Remote Wakeup"
]
},
"MaxPower": {
"description": "0mA"
},
"interface_descriptors": [
{
"bLength": {
"value": "9"
},
...
"bInterfaceProtocol": {
"value": "0",
"description": "Full speed (or root) hub"
},
"iInterface": {
"value": "0"
},
"endpoint_descriptors": [
{
"bLength": {
"value": "7"
},
...
"bmAttributes": {
"value": "3",
"attributes": [
"Transfer Type Interrupt",
"Synch Type None",
"Usage Type Data"
]
},
"wMaxPacketSize": {
"value": "0x0002",
"description": "1x 2 bytes"
},
"bInterval": {
"value": "255"
}
}
]
}
]
}
},
"hub_descriptor": {
"bLength": {
"value": "9"
},
...
"wHubCharacteristic": {
"value": "0x000a",
"attributes": [
"No power switching (usb 1.0)",
"Per-port overcurrent protection"
]
},
...
"hub_port_status": {
"Port 1": {
"value": "0000.0103",
"attributes": [
"power",
"enable",
"connect"
]
},
"Port 2": {
"value": "0000.0103",
"attributes": [
"power",
"enable",
"connect"
]
}
}
},
"device_status": {
"value": "0x0001",
"description": "Self Powered"
}
}
]
## info
```python
info()
```
Provides parser metadata (version, author, etc.)
## parse
```python
parse(data, raw=False, quiet=False)
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
## Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -72,4 +72,4 @@ Returns:
## Parser Information
Compatibility: linux, darwin, freebsd
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -73,4 +73,4 @@ Module Example:
"""
name = 'jc'
__version__ = '1.17.0'
__version__ = '1.17.1'

View File

@ -53,6 +53,7 @@ parsers = [
'crontab',
'crontab-u',
'csv',
'csv-s',
'date',
'df',
'dig',
@ -85,6 +86,7 @@ parsers = [
'lsblk',
'lsmod',
'lsof',
'lsusb',
'mount',
'netstat',
'ntpq',

131
jc/parsers/csv_s.py Normal file
View File

@ -0,0 +1,131 @@
"""jc - JSON CLI output utility `csv` file streaming parser
> This streaming parser outputs JSON Lines
The `csv` streaming parser will attempt to automatically detect the delimiter character. If the delimiter cannot be detected it will default to comma. The first row of the file must be a header row.
Note: The first 100 rows are read into memory to enable delimiter detection, then the rest of the rows are loaded lazily.
Usage (cli):
$ cat file.csv | jc --csv-s
Usage (module):
import jc.parsers.csv_s
result = jc.parsers.csv_s.parse(csv_output)
Schema:
csv file converted to a Dictionary: https://docs.python.org/3/library/csv.html
{
"column_name1": string,
"column_name2": string
}
Examples:
$ cat homes.csv
"Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes"
142, 160, 28, 10, 5, 3, 60, 0.28, 3167
175, 180, 18, 8, 4, 1, 12, 0.43, 4033
129, 132, 13, 6, 3, 1, 41, 0.33, 1471
...
$ cat homes.csv | jc --csv-s
{"Sell":"142","List":"160","Living":"28","Rooms":"10","Beds":"5","Baths":"3","Age":"60","Acres":"0.28","Taxes":"3167"}
{"Sell":"175","List":"180","Living":"18","Rooms":"8","Beds":"4","Baths":"1","Age":"12","Acres":"0.43","Taxes":"4033"}
{"Sell":"129","List":"132","Living":"13","Rooms":"6","Beds":"3","Baths":"1","Age":"41","Acres":"0.33","Taxes":"1471"}
...
"""
import itertools
import csv
import jc.utils
from jc.utils import stream_success, stream_error
from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'CSV file streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the python standard csv library'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
streaming = True
__version__ = info.version
def _process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Each Dictionary represents a row in the csv file.
"""
# No further processing
return proc_data
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
"""
Main text parsing generator function. Returns an iterator object.
Parameters:
data: (iterable) line-based text data to parse (e.g. sys.stdin or str.splitlines())
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
ignore_exceptions: (boolean) ignore parsing exceptions if True
Yields:
Dictionary. Raw or processed structured data.
Returns:
Iterator object
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
# convert data to an iterable in case a sequence like a list is used as input.
# this allows the exhaustion of the input so we don't double-process later.
data = iter(data)
temp_list = []
# first, load the first 100 lines into a list to detect the CSV dialect
for line in itertools.islice(data, 100):
temp_list.append(line)
# check for Python bug that does not split on `\r` newlines from sys.stdin correctly
# https://bugs.python.org/issue45617
if len(temp_list) == 1:
raise ParseError('Unable to detect line endings. Please try the non-streaming CSV parser instead.')
sniffdata = '\n'.join(temp_list)
dialect = None
try:
dialect = csv.Sniffer().sniff(sniffdata)
except Exception:
pass
# chain `temp_list` and `data` together to lazy load the rest of the CSV data
new_data = itertools.chain(temp_list, data)
reader = csv.DictReader(new_data, dialect=dialect)
for row in reader:
try:
yield stream_success(row, ignore_exceptions) if raw else stream_success(_process(row), ignore_exceptions)
except Exception as e:
yield stream_error(e, ignore_exceptions, row)

View File

@ -63,7 +63,7 @@ import jc.parsers.universal
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.3'
version = '1.4'
description = '`file` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@ -116,7 +116,14 @@ def parse(data, raw=False, quiet=False):
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()):
linedata = line.rsplit(': ', maxsplit=1)
# fix case for gzip files where description contains ': ' delimiter
if 'gzip compressed data, last modified: ' in line:
linedata = line.split(': ', maxsplit=1)
# use rsplit to correctly grab filenames containing ': ' delimiter text
else:
linedata = line.rsplit(': ', maxsplit=1)
try:
filename = linedata[0].strip()

844
jc/parsers/lsusb.py Normal file
View File

@ -0,0 +1,844 @@
"""jc - JSON CLI output utility `lsusb` command output parser
Supports the `-v` option or no options.
Usage (cli):
$ lsusb -v | jc --lsusb
or
$ jc lsusb -v
Usage (module):
import jc.parsers.lsusb
result = jc.parsers.lsusb.parse(lsusb_command_output)
Schema:
Note: <item> object keynames are assigned directly from the lsusb output.
If there are duplicate <item> names in a section, only the last one is converted.
[
{
"bus": string,
"device": string,
"id": string,
"description": string,
"device_descriptor": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
},
"configuration_descriptor": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
},
"interface_association": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"interface_descriptors": [
{
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
},
"cdc_header": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"cdc_call_management": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"cdc_acm": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"cdc_union": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
},
"endpoint_descriptors": [
{
"<item>": {
"value": string,
"description": string,
"attributes": [
string
]
}
}
]
}
]
}
},
"hub_descriptor": {
"<item>": {
"value": string,
"description": string,
"attributes": [
string,
]
},
"hub_port_status": {
"<item>": {
"value": string,
"attributes": [
string
]
}
}
},
"device_status": {
"value": string,
"description": string
}
}
]
Examples:
$ lsusb -v | jc --lsusb -p
[
{
"bus": "002",
"device": "001",
"id": "1d6b:0001",
"description": "Linux Foundation 1.1 root hub",
"device_descriptor": {
"bLength": {
"value": "18"
},
"bDescriptorType": {
"value": "1"
},
"bcdUSB": {
"value": "1.10"
},
...
"bNumConfigurations": {
"value": "1"
},
"configuration_descriptor": {
"bLength": {
"value": "9"
},
...
"iConfiguration": {
"value": "0"
},
"bmAttributes": {
"value": "0xe0",
"attributes": [
"Self Powered",
"Remote Wakeup"
]
},
"MaxPower": {
"description": "0mA"
},
"interface_descriptors": [
{
"bLength": {
"value": "9"
},
...
"bInterfaceProtocol": {
"value": "0",
"description": "Full speed (or root) hub"
},
"iInterface": {
"value": "0"
},
"endpoint_descriptors": [
{
"bLength": {
"value": "7"
},
...
"bmAttributes": {
"value": "3",
"attributes": [
"Transfer Type Interrupt",
"Synch Type None",
"Usage Type Data"
]
},
"wMaxPacketSize": {
"value": "0x0002",
"description": "1x 2 bytes"
},
"bInterval": {
"value": "255"
}
}
]
}
]
}
},
"hub_descriptor": {
"bLength": {
"value": "9"
},
...
"wHubCharacteristic": {
"value": "0x000a",
"attributes": [
"No power switching (usb 1.0)",
"Per-port overcurrent protection"
]
},
...
"hub_port_status": {
"Port 1": {
"value": "0000.0103",
"attributes": [
"power",
"enable",
"connect"
]
},
"Port 2": {
"value": "0000.0103",
"attributes": [
"power",
"enable",
"connect"
]
}
}
},
"device_status": {
"value": "0x0001",
"description": "Self Powered"
}
}
]
"""
import jc.utils
from jc.parsers.universal import sparse_table_parse
from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`lsusb` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
magic_commands = ['lsusb']
__version__ = info.version
def _process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
List of Dictionaries. Structured to conform to the schema.
"""
# no further processing
return proc_data
class _NestedDict(dict):
# for ease of creating/updating nested dictionary structures
# https://stackoverflow.com/questions/5369723/multi-level-defaultdict-with-variable-depth
# https://ohuiginn.net/mt/2010/07/nested_dictionaries_in_python.html
def __getitem__(self, key):
if key in self:
return self.get(key)
return self.setdefault(key, _NestedDict())
class _LsUsb():
def __init__(self):
self.raw_output = []
self.output_line = _NestedDict()
self.section = ''
self.old_section = ''
self.bus_idx = -1
self.interface_descriptor_idx = -1
self.endpoint_descriptor_idx = -1
self.last_item = ''
self.last_indent = 0
self.attribute_value = False
self.bus_list = []
self.device_descriptor_list = []
self.configuration_descriptor_list = []
self.interface_association_list = []
self.interface_descriptor_list = []
self.interface_descriptor_attribute_list = []
self.cdc_header_list = []
self.cdc_call_management_list = []
self.cdc_acm_list = []
self.cdc_union_list = []
self.endpoint_descriptor_list = []
self.hid_device_descriptor_list = []
self.report_descriptors_list = []
self.hub_descriptor_list = []
self.hub_port_status_list = []
self.device_status_list = []
@staticmethod
def _count_indent(line):
indent = 0
for char in line:
if char == ' ':
indent += 1
continue
break
return indent
def _add_attributes(self, line):
indent = self._count_indent(line)
# determine whether this is a top-level value item or lower-level attribute
if indent > self.last_indent and self.old_section == self.section:
self.attribute_value = True
elif indent == self.last_indent and self.attribute_value and self.old_section == self.section:
self.attribute_value = True
else:
self.attribute_value = False
# section_header is formatted with the correct spacing to be used with
# jc.parsers.universal.sparse_table_parse(). Pad end of string to be at least len of 25
section_header = 'key val description'
temp_obj = [section_header, line.strip() + (' ' * 25)]
temp_obj = sparse_table_parse(temp_obj)
temp_obj = temp_obj[0]
line_obj = {
temp_obj['key']: {
'value': temp_obj['val'],
'description': temp_obj['description'],
'_state': {
'attribute_value': self.attribute_value,
'last_item': self.last_item,
'bus_idx': self.bus_idx,
'interface_descriptor_idx': self.interface_descriptor_idx,
'endpoint_descriptor_idx': self.endpoint_descriptor_idx
}
}
}
if line_obj[temp_obj['key']]['value'] is None:
del line_obj[temp_obj['key']]['value']
if line_obj[temp_obj['key']]['description'] is None:
del line_obj[temp_obj['key']]['description']
self.old_section = self.section
self.last_indent = indent
if not self.attribute_value:
self.last_item = temp_obj['key']
return line_obj
def _add_hub_port_status_attributes(self, line):
# Port 1: 0000.0103 power enable connect
first_split = line.split(': ', maxsplit=1)
port_field = first_split[0].strip()
second_split = first_split[1].split(maxsplit=1)
port_val = second_split[0]
attributes = second_split[1].split()
return {
port_field: {
'value': port_val,
'attributes': attributes,
'_state': {
'bus_idx': self.bus_idx
}
}
}
def _add_device_status_attributes(self, line):
return {
'description': line.strip(),
'_state': {
'bus_idx': self.bus_idx
}
}
def _set_sections(self, line):
# ignore blank lines
if not line:
self.section = ''
self.attribute_value = False
return True
# bus information is on the same line so need to extract data immediately and set indexes
if line.startswith('Bus '):
self.section = 'bus'
self.bus_idx += 1
self.interface_descriptor_idx = -1
self.endpoint_descriptor_idx = -1
self.attribute_value = False
line_split = line.strip().split(maxsplit=6)
self.bus_list.append(
{
'bus': line_split[1],
'device': line_split[3][:-1],
'id': line_split[5],
'description': (line_split[6:7] or [None])[0], # way to get a list item or None
'_state': {
'bus_idx': self.bus_idx
}
}
)
return True
# This section is a list, so need to update indexes
if line.startswith(' Interface Descriptor:'):
self.section = 'interface_descriptor'
self.interface_descriptor_idx += 1
self.endpoint_descriptor_idx = -1
self.attribute_value = False
return True
# This section is a list, so need to update the index
if line.startswith(' Endpoint Descriptor:'):
self.section = 'endpoint_descriptor'
self.endpoint_descriptor_idx += 1
self.attribute_value = False
return True
# some device status information is displayed on the initial line so need to extract immediately
if line.startswith('Device Status:'):
self.section = 'device_status'
self.attribute_value = False
line_split = line.strip().split(':', maxsplit=1)
self.device_status_list.append(
{
'value': line_split[1].strip(),
'_state': {
'bus_idx': self.bus_idx
}
}
)
return True
# set the rest of the sections
string_section_map = {
'Device Descriptor:': 'device_descriptor',
' Configuration Descriptor:': 'configuration_descriptor',
' Interface Association:': 'interface_association',
' CDC Header:': 'cdc_header',
' CDC Call Management:': 'cdc_call_management',
' CDC ACM:': 'cdc_acm',
' CDC Union:': 'cdc_union',
' HID Device Descriptor:': 'hid_device_descriptor',
' Report Descriptors:': 'report_descriptors',
'Hub Descriptor:': 'hub_descriptor',
' Hub Port Status:': 'hub_port_status'
}
for sec_string, section_val in string_section_map.items():
if line.startswith(sec_string):
self.section = section_val
self.attribute_value = False
return True
return False
def _populate_lists(self, line):
section_list_map = {
'device_descriptor': self.device_descriptor_list,
'configuration_descriptor': self.configuration_descriptor_list,
'interface_association': self.interface_association_list,
'interface_descriptor': self.interface_descriptor_list,
'cdc_header': self.cdc_header_list,
'cdc_call_management': self.cdc_call_management_list,
'cdc_acm': self.cdc_acm_list,
'cdc_union': self.cdc_union_list,
'hid_device_descriptor': self.hid_device_descriptor_list,
'report_descriptors': self.report_descriptors_list,
'endpoint_descriptor': self.endpoint_descriptor_list,
'hub_descriptor': self.hub_descriptor_list
}
for sec in section_list_map:
if line.startswith(' ') and self.section == sec:
section_list_map[self.section].append(self._add_attributes(line))
return True
# special handling of these sections
if line.startswith(' ') and self.section == 'hub_port_status':
self.hub_port_status_list.append(self._add_hub_port_status_attributes(line))
return True
if line.startswith(' ') and self.section == 'device_status':
self.device_status_list.append(self._add_device_status_attributes(line))
return True
return False
def _populate_schema(self):
"""
Schema:
= {}
['device_descriptor'] = {}
['device_descriptor']['configuration_descriptor'] = {}
['device_descriptor']['configuration_descriptor']['interface_association'] = {}
['device_descriptor']['configuration_descriptor']['interface_descriptors'] = []
['device_descriptor']['configuration_descriptor']['interface_descriptors'][0] = {}
['device_descriptor']['configuration_descriptor']['interface_descriptors'][0]['cdc_header'] = {}
['device_descriptor']['configuration_descriptor']['interface_descriptors'][0]['cdc_call_management'] = {}
['device_descriptor']['configuration_descriptor']['interface_descriptors'][0]['cdc_acm'] = {}
['device_descriptor']['configuration_descriptor']['interface_descriptors'][0]['cdc_union'] = {}
['device_descriptor']['configuration_descriptor']['interface_descriptors'][0]['hid_device_descriptor'] = {}
['device_descriptor']['configuration_descriptor']['interface_descriptors'][0]['endpoint_descriptors'] = []
['device_descriptor']['configuration_descriptor']['interface_descriptors'][0]['endpoint_descriptors'][0] = {}
['hub_descriptor'] = {}
['hub_descriptor']['hub_port_status'] = {}
['device_status'] = {}
"""
for idx, item in enumerate(self.bus_list):
if self.output_line:
self.raw_output.append(self.output_line)
self.output_line = _NestedDict()
del item['_state']
self.output_line.update(item)
for dd in self.device_descriptor_list:
keyname = tuple(dd.keys())[0]
if '_state' in dd[keyname] and dd[keyname]['_state']['bus_idx'] == idx:
# is this a top level value or an attribute?
if dd[keyname]['_state']['attribute_value']:
last_item = dd[keyname]['_state']['last_item']
if 'attributes' not in self.output_line['device_descriptor'][last_item]:
self.output_line['device_descriptor'][last_item]['attributes'] = []
this_attribute = f'{keyname} {dd[keyname].get("value", "")} {dd[keyname].get("description", "")}'.strip()
self.output_line['device_descriptor'][last_item]['attributes'].append(this_attribute)
continue
self.output_line['device_descriptor'].update(dd)
del self.output_line['device_descriptor'][keyname]['_state']
for cd in self.configuration_descriptor_list:
keyname = tuple(cd.keys())[0]
if '_state' in cd[keyname] and cd[keyname]['_state']['bus_idx'] == idx:
# is this a top level value or an attribute?
if cd[keyname]['_state']['attribute_value']:
last_item = cd[keyname]['_state']['last_item']
if 'attributes' not in self.output_line['device_descriptor']['configuration_descriptor'][last_item]:
self.output_line['device_descriptor']['configuration_descriptor'][last_item]['attributes'] = []
this_attribute = f'{keyname} {cd[keyname].get("value", "")} {cd[keyname].get("description", "")}'.strip()
self.output_line['device_descriptor']['configuration_descriptor'][last_item]['attributes'].append(this_attribute)
continue
self.output_line['device_descriptor']['configuration_descriptor'].update(cd)
del self.output_line['device_descriptor']['configuration_descriptor'][keyname]['_state']
for ia in self.interface_association_list:
keyname = tuple(ia.keys())[0]
if '_state' in ia[keyname] and ia[keyname]['_state']['bus_idx'] == idx:
# is this a top level value or an attribute?
if ia[keyname]['_state']['attribute_value']:
last_item = ia[keyname]['_state']['last_item']
if 'attributes' not in self.output_line['device_descriptor']['configuration_descriptor']['interface_association'][last_item]:
self.output_line['device_descriptor']['configuration_descriptor']['interface_association'][last_item]['attributes'] = []
this_attribute = f'{keyname} {ia[keyname].get("value", "")} {ia[keyname].get("description", "")}'.strip()
self.output_line['device_descriptor']['configuration_descriptor']['interface_association'][last_item]['attributes'].append(this_attribute)
continue
self.output_line['device_descriptor']['configuration_descriptor']['interface_association'].update(ia)
del self.output_line['device_descriptor']['configuration_descriptor']['interface_association'][keyname]['_state']
# add interface_descriptor key if it doesn't exist and there are entries for this bus
for iface_attrs in self.interface_descriptor_list:
keyname = tuple(iface_attrs.keys())[0]
if '_state' in iface_attrs[keyname] and iface_attrs[keyname]['_state']['bus_idx'] == idx:
self.output_line['device_descriptor']['configuration_descriptor']['interface_descriptors'] = []
# find max index for this bus idx, then iterate over that range
i_desc_iters = -1
for iface_attrs in self.interface_descriptor_list:
keyname = tuple(iface_attrs.keys())[0]
if '_state' in iface_attrs[keyname] and iface_attrs[keyname]['_state']['bus_idx'] == idx:
i_desc_iters = iface_attrs[keyname]['_state']['interface_descriptor_idx']
# create the interface descriptor object
if i_desc_iters > -1:
for iface_idx in range(i_desc_iters + 1):
i_desc_obj = _NestedDict()
for iface_attrs in self.interface_descriptor_list:
keyname = tuple(iface_attrs.keys())[0]
if '_state' in iface_attrs[keyname] and iface_attrs[keyname]['_state']['bus_idx'] == idx and iface_attrs[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
# is this a top level value or an attribute?
if iface_attrs[keyname]['_state']['attribute_value']:
last_item = iface_attrs[keyname]['_state']['last_item']
if 'attributes' not in i_desc_obj[last_item]:
i_desc_obj[last_item]['attributes'] = []
this_attribute = f'{keyname} {iface_attrs[keyname].get("value", "")} {iface_attrs[keyname].get("description", "")}'.strip()
i_desc_obj[last_item]['attributes'].append(this_attribute)
continue
del iface_attrs[keyname]['_state']
i_desc_obj.update(iface_attrs)
# add other nodes to the object (cdc_header, endpoint descriptors, etc.)
for ch in self.cdc_header_list:
keyname = tuple(ch.keys())[0]
if '_state' in ch[keyname] and ch[keyname]['_state']['bus_idx'] == idx and ch[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
# is this a top level value or an attribute?
if ch[keyname]['_state']['attribute_value']:
last_item = ch[keyname]['_state']['last_item']
if 'attributes' not in i_desc_obj['cdc_header'][last_item]:
i_desc_obj['cdc_header'][last_item]['attributes'] = []
this_attribute = f'{keyname} {ch[keyname].get("value", "")} {ch[keyname].get("description", "")}'.strip()
i_desc_obj['cdc_header'][last_item]['attributes'].append(this_attribute)
continue
i_desc_obj['cdc_header'].update(ch)
del i_desc_obj['cdc_header'][keyname]['_state']
for ccm in self.cdc_call_management_list:
keyname = tuple(ccm.keys())[0]
if '_state' in ccm[keyname] and ccm[keyname]['_state']['bus_idx'] == idx and ccm[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
# is this a top level value or an attribute?
if ccm[keyname]['_state']['attribute_value']:
last_item = ccm[keyname]['_state']['last_item']
if 'attributes' not in i_desc_obj['cdc_call_management'][last_item]:
i_desc_obj['cdc_call_management'][last_item]['attributes'] = []
this_attribute = f'{keyname} {ccm[keyname].get("value", "")} {ccm[keyname].get("description", "")}'.strip()
i_desc_obj['cdc_call_management'][last_item]['attributes'].append(this_attribute)
continue
i_desc_obj['cdc_call_management'].update(ccm)
del i_desc_obj['cdc_call_management'][keyname]['_state']
for ca in self.cdc_acm_list:
keyname = tuple(ca.keys())[0]
if '_state' in ca[keyname] and ca[keyname]['_state']['bus_idx'] == idx and ca[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
# is this a top level value or an attribute?
if ca[keyname]['_state']['attribute_value']:
last_item = ca[keyname]['_state']['last_item']
if 'attributes' not in i_desc_obj['cdc_acm'][last_item]:
i_desc_obj['cdc_acm'][last_item]['attributes'] = []
this_attribute = f'{keyname} {ca[keyname].get("value", "")} {ca[keyname].get("description", "")}'.strip()
i_desc_obj['cdc_acm'][last_item]['attributes'].append(this_attribute)
continue
i_desc_obj['cdc_acm'].update(ca)
del i_desc_obj['cdc_acm'][keyname]['_state']
for cu in self.cdc_union_list:
keyname = tuple(cu.keys())[0]
if '_state' in cu[keyname] and cu[keyname]['_state']['bus_idx'] == idx and cu[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
# is this a top level value or an attribute?
if cu[keyname]['_state']['attribute_value']:
last_item = cu[keyname]['_state']['last_item']
if 'attributes' not in i_desc_obj['cdc_union'][last_item]:
i_desc_obj['cdc_union'][last_item]['attributes'] = []
this_attribute = f'{keyname} {cu[keyname].get("value", "")} {cu[keyname].get("description", "")}'.strip()
i_desc_obj['cdc_union'][last_item]['attributes'].append(this_attribute)
continue
i_desc_obj['cdc_union'].update(cu)
del i_desc_obj['cdc_union'][keyname]['_state']
for hidd in self.hid_device_descriptor_list:
keyname = tuple(hidd.keys())[0]
if '_state' in hidd[keyname] and hidd[keyname]['_state']['bus_idx'] == idx and hidd[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
# is this a top level value or an attribute?
if hidd[keyname]['_state']['attribute_value']:
last_item = hidd[keyname]['_state']['last_item']
if 'attributes' not in i_desc_obj['hid_device_descriptor'][last_item]:
i_desc_obj['hid_device_descriptor'][last_item]['attributes'] = []
this_attribute = f'{keyname} {hidd[keyname].get("value", "")} {hidd[keyname].get("description", "")}'.strip()
i_desc_obj['hid_device_descriptor'][last_item]['attributes'].append(this_attribute)
continue
i_desc_obj['hid_device_descriptor'].update(hidd)
del i_desc_obj['hid_device_descriptor'][keyname]['_state']
# Not Implemented: Report Descriptors (need more samples)
# for rd in self.report_descriptors_list:
# keyname = tuple(rd.keys())[0]
# if '_state' in rd[keyname] and rd[keyname]['_state']['bus_idx'] == idx and rd[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
# i_desc_obj['hid_device_descriptor']['report_descriptors'].update(rd)
# del i_desc_obj['hid_device_descriptor']['report_descriptors'][keyname]['_state']
# add endpoint_descriptor key if it doesn't exist and there are entries for this interface_descriptor
for endpoint_attrs in self.endpoint_descriptor_list:
keyname = tuple(endpoint_attrs.keys())[0]
if '_state' in endpoint_attrs[keyname] and endpoint_attrs[keyname]['_state']['bus_idx'] == idx and endpoint_attrs[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
i_desc_obj['endpoint_descriptors'] = []
# find max index for this endpoint_descriptor idx, then iterate over that range
e_desc_iters = -1
for endpoint_attrs in self.endpoint_descriptor_list:
keyname = tuple(endpoint_attrs.keys())[0]
if '_state' in endpoint_attrs[keyname] and endpoint_attrs[keyname]['_state']['bus_idx'] == idx and endpoint_attrs[keyname]['_state']['interface_descriptor_idx'] == iface_idx:
e_desc_iters = endpoint_attrs[keyname]['_state']['endpoint_descriptor_idx']
# create the endpoint descriptor object
if e_desc_iters > -1:
for endpoint_idx in range(e_desc_iters + 1):
e_desc_obj = {}
for endpoint_attrs in self.endpoint_descriptor_list:
keyname = tuple(endpoint_attrs.keys())[0]
if '_state' in endpoint_attrs[keyname] and endpoint_attrs[keyname]['_state']['bus_idx'] == idx and endpoint_attrs[keyname]['_state']['interface_descriptor_idx'] == iface_idx and endpoint_attrs[keyname]['_state']['endpoint_descriptor_idx'] == endpoint_idx:
# is this a top level value or an attribute?
if endpoint_attrs[keyname]['_state']['attribute_value']:
last_item = endpoint_attrs[keyname]['_state']['last_item']
if 'attributes' not in e_desc_obj[last_item]:
e_desc_obj[last_item]['attributes'] = []
this_attribute = f'{keyname} {endpoint_attrs[keyname].get("value", "")} {endpoint_attrs[keyname].get("description", "")}'.strip()
e_desc_obj[last_item]['attributes'].append(this_attribute)
continue
e_desc_obj.update(endpoint_attrs)
del endpoint_attrs[keyname]['_state']
i_desc_obj['endpoint_descriptors'].append(e_desc_obj)
# add the object to the list of interface descriptors
self.output_line['device_descriptor']['configuration_descriptor']['interface_descriptors'].append(i_desc_obj)
for hd in self.hub_descriptor_list:
keyname = tuple(hd.keys())[0]
if '_state' in hd[keyname] and hd[keyname]['_state']['bus_idx'] == idx:
# is this a top level value or an attribute?
if hd[keyname]['_state']['attribute_value']:
last_item = hd[keyname]['_state']['last_item']
if 'attributes' not in self.output_line['hub_descriptor'][last_item]:
self.output_line['hub_descriptor'][last_item]['attributes'] = []
this_attribute = f'{keyname} {hd[keyname].get("value", "")} {hd[keyname].get("description", "")}'.strip()
self.output_line['hub_descriptor'][last_item]['attributes'].append(this_attribute)
continue
self.output_line['hub_descriptor'].update(hd)
del self.output_line['hub_descriptor'][keyname]['_state']
for hps in self.hub_port_status_list:
keyname = tuple(hps.keys())[0]
if '_state' in hps[keyname] and hps[keyname]['_state']['bus_idx'] == idx:
self.output_line['hub_descriptor']['hub_port_status'].update(hps)
del self.output_line['hub_descriptor']['hub_port_status'][keyname]['_state']
for ds in self.device_status_list:
if '_state' in ds and ds['_state']['bus_idx'] == idx:
self.output_line['device_status'].update(ds)
del self.output_line['device_status']['_state']
def parse(data, raw=False, quiet=False):
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) output preprocessed JSON if True
quiet: (boolean) suppress warning messages if True
Returns:
List of Dictionaries. Raw or processed structured data.
"""
if not quiet:
jc.utils.compatibility(__name__, info.compatible)
lsusb = _LsUsb()
if jc.utils.has_data(data):
for line in data.splitlines():
# only -v option or no options are supported
if line.startswith('/'):
raise ParseError('Only `lsusb` or `lsusb -v` are supported.')
# sections
if lsusb._set_sections(line):
continue
# create section lists and schema
if lsusb._populate_lists(line):
continue
# populate the schema
lsusb._populate_schema()
# add any final output object if it exists and return the raw_output list
if lsusb.output_line:
lsusb.raw_output.append(lsusb.output_line)
return lsusb.raw_output if raw else _process(lsusb.raw_output)

View File

@ -48,7 +48,7 @@ from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.5'
version = '1.6'
description = '`uname -a` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@ -98,8 +98,8 @@ def parse(data, raw=False, quiet=False):
if jc.utils.has_data(data):
# check for OSX output
if data.startswith('Darwin'):
# check for macOS or FreeBSD output
if data.startswith('Darwin') or data.startswith('FreeBSD'):
parsed_line = data.split()
if len(parsed_line) < 5:
@ -113,6 +113,19 @@ def parse(data, raw=False, quiet=False):
# otherwise use linux parser
else:
# fixup for cases where 'machine' exists but 'processor' and 'hardware_platform' fields are blank.
# if the fields exist then at least two of the three will be the same.
# if the fields do not exist then none of the fields in those positions will be the same.
# case of only two existing is undefined. Must either be one or all three existing, otherwise
# there will be unexpected results during parsing.
fixup = data.split()
if len(fixup) >= 4:
fixup_set = set([fixup[-2], fixup[-3], fixup[-4]])
if len(fixup_set) > 2:
fixup.insert(-1, 'unknown')
fixup.insert(-1, 'unknown')
data = ' '.join(fixup)
parsed_line = data.split(maxsplit=3)
if len(parsed_line) < 3:
@ -125,8 +138,8 @@ def parse(data, raw=False, quiet=False):
parsed_line = parsed_line[-1].rsplit(maxsplit=4)
raw_output['operating_system'] = parsed_line.pop(-1)
raw_output['hardware_platform'] = parsed_line.pop(-1)
raw_output['processor'] = parsed_line.pop(-1)
raw_output['hardware_platform'] = parsed_line.pop(-1)
raw_output['machine'] = parsed_line.pop(-1)
raw_output['kernel_version'] = parsed_line.pop(0)

View File

@ -1,4 +1,4 @@
.TH jc 1 2021-09-27 1.17.0 "JSON CLI output utility"
.TH jc 1 2021-10-30 1.17.1 "JSON CLI output utility"
.SH NAME
jc \- JSONifies the output of many CLI tools and file-types
.SH SYNOPSIS
@ -62,6 +62,11 @@ Parsers:
\fB--csv\fP
CSV file parser
.TP
.B
\fB--csv-s\fP
CSV file streaming parser
.TP
.B
\fB--date\fP
@ -222,6 +227,11 @@ Key/Value file parser
\fB--lsof\fP
`lsof` command parser
.TP
.B
\fB--lsusb\fP
`lsusb` command parser
.TP
.B
\fB--mount\fP

View File

@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
setuptools.setup(
name='jc',
version='1.17.0',
version='1.17.1',
author='Kelly Brazil',
author_email='kellyjonbrazil@gmail.com',
description='Converts the output of popular command-line tools and file-types to JSON.',

View File

@ -0,0 +1 @@
[{"bus":"003","device":"090","id":"1915:521a","description":"Nordic Semiconductor ASA nRF52 USB CDC BLE Demo","device_descriptor":{"bLength":{"value":"18"},"bDescriptorType":{"value":"1"},"bcdUSB":{"value":"2.00"},"bDeviceClass":{"value":"0"},"bDeviceSubClass":{"value":"0"},"bDeviceProtocol":{"value":"0"},"bMaxPacketSize0":{"value":"64"},"idVendor":{"value":"0x1915","description":"Nordic Semiconductor ASA"},"idProduct":{"value":"0x521a"},"bcdDevice":{"value":"1.00"},"iManufacturer":{"value":"1","description":"Nordic Semiconductor"},"iProduct":{"value":"2","description":"nRF52 USB CDC BLE Demo"},"iSerial":{"value":"3","description":"F42DE60BE261"},"bNumConfigurations":{"value":"1"},"configuration_descriptor":{"bLength":{"value":"9"},"bDescriptorType":{"value":"2"},"wTotalLength":{"value":"0x004b"},"bNumInterfaces":{"value":"2"},"bConfigurationValue":{"value":"1"},"iConfiguration":{"value":"4"},"bmAttributes":{"value":"0xc0","attributes":["Self Powered"]},"MaxPower":{"description":"100mA"},"interface_association":{"bLength":{"value":"8"},"bDescriptorType":{"value":"11"},"bFirstInterface":{"value":"0"},"bInterfaceCount":{"value":"2"},"bFunctionClass":{"value":"2","description":"Communications"},"bFunctionSubClass":{"value":"2","description":"Abstract (modem)"},"bFunctionProtocol":{"value":"1","description":"AT-commands (v.25ter)"},"iFunction":{"value":"0"}},"interface_descriptors":[{"bLength":{"value":"9"},"bDescriptorType":{"value":"4"},"bInterfaceNumber":{"value":"0"},"bAlternateSetting":{"value":"0"},"bNumEndpoints":{"value":"1"},"bInterfaceClass":{"value":"2","description":"Communications"},"bInterfaceSubClass":{"value":"2","description":"Abstract (modem)"},"bInterfaceProtocol":{"value":"1","description":"AT-commands (v.25ter)"},"iInterface":{"value":"0"},"cdc_header":{"bcdCDC":{"value":"1.10"}},"cdc_call_management":{"bmCapabilities":{"value":"0x03","attributes":["call management","use DataInterface"]},"bDataInterface":{"value":"1"}},"cdc_acm":{"bmCapabilities":{"value":"0x02","attributes":["line coding and serial state"]}},"cdc_union":{"bMasterInterface":{"value":"0"},"bSlaveInterface":{"value":"1"}},"endpoint_descriptors":[{"bLength":{"value":"7"},"bDescriptorType":{"value":"5"},"bEndpointAddress":{"value":"0x82","description":"EP 2 IN"},"bmAttributes":{"value":"3","attributes":["Transfer Type Interrupt","Synch Type None","Usage Type Data"]},"wMaxPacketSize":{"value":"0x0040","description":"1x 64 bytes"},"bInterval":{"value":"16"}}]},{"bLength":{"value":"9"},"bDescriptorType":{"value":"4"},"bInterfaceNumber":{"value":"1"},"bAlternateSetting":{"value":"0"},"bNumEndpoints":{"value":"2"},"bInterfaceClass":{"value":"10","description":"CDC Data"},"bInterfaceSubClass":{"value":"0"},"bInterfaceProtocol":{"value":"0"},"iInterface":{"value":"0"},"endpoint_descriptors":[{"bLength":{"value":"7"},"bDescriptorType":{"value":"5"},"bEndpointAddress":{"value":"0x81","description":"EP 1 IN"},"bmAttributes":{"value":"2","attributes":["Transfer Type Bulk","Synch Type None","Usage Type Data"]},"wMaxPacketSize":{"value":"0x0040","description":"1x 64 bytes"},"bInterval":{"value":"0"}},{"bLength":{"value":"7"},"bDescriptorType":{"value":"5"},"bEndpointAddress":{"value":"0x01","description":"EP 1 OUT"},"bmAttributes":{"value":"2","attributes":["Transfer Type Bulk","Synch Type None","Usage Type Data"]},"wMaxPacketSize":{"value":"0x0040","description":"1x 64 bytes"},"bInterval":{"value":"0"}}]}]}}}]

View File

@ -0,0 +1,100 @@
Bus 003 Device 090: ID 1915:521a Nordic Semiconductor ASA nRF52 USB CDC BLE Demo
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x1915 Nordic Semiconductor ASA
idProduct 0x521a
bcdDevice 1.00
iManufacturer 1 Nordic Semiconductor
iProduct 2 nRF52 USB CDC BLE Demo
iSerial 3 F42DE60BE261
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x004b
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 4
bmAttributes 0xc0
Self Powered
MaxPower 100mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 1 AT-commands (v.25ter)
iFunction 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 0
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x03
call management
use DataInterface
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0

File diff suppressed because one or more lines are too long

509
tests/fixtures/centos-7.7/lsusb-v.out vendored Normal file
View File

@ -0,0 +1,509 @@
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 9 Hub
bDeviceSubClass 0 Unused
bDeviceProtocol 0 Full speed (or root) hub
bMaxPacketSize0 64
idVendor 0x1d6b Linux Foundation
idProduct 0x0002 2.0 root hub
bcdDevice 3.10
iManufacturer 3 Linux 3.10.0-1062.1.2.el7.x86_64 ehci_hcd
iProduct 2 EHCI Host Controller
iSerial 1 0000:02:02.0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 25
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xe0
Self Powered
Remote Wakeup
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 9 Hub
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0 Full speed (or root) hub
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0004 1x 4 bytes
bInterval 12
Hub Descriptor:
bLength 9
bDescriptorType 41
nNbrPorts 6
wHubCharacteristic 0x000a
No power switching (usb 1.0)
Per-port overcurrent protection
bPwrOn2PwrGood 10 * 2 milli seconds
bHubContrCurrent 0 milli Ampere
DeviceRemovable 0x00
PortPwrCtrlMask 0xff
Hub Port Status:
Port 1: 0000.0100 power
Port 2: 0000.0100 power
Port 3: 0000.0100 power
Port 4: 0000.0100 power
Port 5: 0000.0100 power
Port 6: 0000.0100 power
Device Status: 0x0001
Self Powered
Bus 002 Device 004: ID 0e0f:0008 VMware, Inc.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 224 Wireless
bDeviceSubClass 1 Radio Frequency
bDeviceProtocol 1 Bluetooth
bMaxPacketSize0 64
idVendor 0x0e0f VMware, Inc.
idProduct 0x0008
bcdDevice 1.00
iManufacturer 1 VMware
iProduct 2 Virtual Bluetooth Adapter
iSerial 3 000650268328
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 177
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0000 1x 0 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0000 1x 0 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0009 1x 9 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0009 1x 9 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 2
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0011 1x 17 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0011 1x 17 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 3
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0019 1x 25 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0019 1x 25 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 4
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0021 1x 33 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0021 1x 33 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 5
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0031 1x 49 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0031 1x 49 bytes
bInterval 1
Device Status: 0x0001
Self Powered
Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 9 Hub
bDeviceSubClass 0 Unused
bDeviceProtocol 0 Full speed (or root) hub
bMaxPacketSize0 8
idVendor 0x0e0f VMware, Inc.
idProduct 0x0002 Virtual USB Hub
bcdDevice 1.00
iManufacturer 1 VMware, Inc.
iProduct 2 VMware Virtual USB Hub
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 25
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 1 VMware, Inc.
bmAttributes 0xe0
Self Powered
Remote Wakeup
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 9 Hub
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0 Full speed (or root) hub
iInterface 1 VMware, Inc.
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0001 1x 1 bytes
bInterval 255
Hub Descriptor:
bLength 9
bDescriptorType 41
nNbrPorts 7
wHubCharacteristic 0x0009
Per-port power switching
Per-port overcurrent protection
bPwrOn2PwrGood 50 * 2 milli seconds
bHubContrCurrent 100 milli Ampere
DeviceRemovable 0x00
PortPwrCtrlMask 0xfe
Hub Port Status:
Port 1: 0000.0103 power enable connect
Port 2: 0000.0100 power
Port 3: 0000.0100 power
Port 4: 0000.0100 power
Port 5: 0000.0100 power
Port 6: 0000.0100 power
Port 7: 0000.0100 power
Device Status: 0x2909
Self Powered
Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0e0f VMware, Inc.
idProduct 0x0003 Virtual Mouse
bcdDevice 1.03
iManufacturer 1 VMware
iProduct 2 VMware Virtual USB Mouse
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 1 VMware
bmAttributes 0xc0
Self Powered
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 2 Mouse
iInterface 1 VMware
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 46
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 1
Device Status: 0x0001
Self Powered
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 9 Hub
bDeviceSubClass 0 Unused
bDeviceProtocol 0 Full speed (or root) hub
bMaxPacketSize0 64
idVendor 0x1d6b Linux Foundation
idProduct 0x0001 1.1 root hub
bcdDevice 3.10
iManufacturer 3 Linux 3.10.0-1062.1.2.el7.x86_64 uhci_hcd
iProduct 2 UHCI Host Controller
iSerial 1 0000:02:00.0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 25
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xe0
Self Powered
Remote Wakeup
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 9 Hub
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0 Full speed (or root) hub
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0002 1x 2 bytes
bInterval 255
Hub Descriptor:
bLength 9
bDescriptorType 41
nNbrPorts 2
wHubCharacteristic 0x000a
No power switching (usb 1.0)
Per-port overcurrent protection
bPwrOn2PwrGood 1 * 2 milli seconds
bHubContrCurrent 0 milli Ampere
DeviceRemovable 0x00
PortPwrCtrlMask 0xff
Hub Port Status:
Port 1: 0000.0103 power enable connect
Port 2: 0000.0103 power enable connect
Device Status: 0x0001
Self Powered

1
tests/fixtures/centos-7.7/lsusb.json vendored Normal file
View File

@ -0,0 +1 @@
[{"bus":"001","device":"001","id":"1d6b:0002","description":"Linux Foundation 2.0 root hub"},{"bus":"002","device":"004","id":"0e0f:0008","description":"VMware, Inc."},{"bus":"002","device":"003","id":"0e0f:0002","description":"VMware, Inc. Virtual USB Hub"},{"bus":"002","device":"002","id":"0e0f:0003","description":"VMware, Inc. Virtual Mouse"},{"bus":"002","device":"001","id":"1d6b:0001","description":"Linux Foundation 1.1 root hub"}]

5
tests/fixtures/centos-7.7/lsusb.out vendored Normal file
View File

@ -0,0 +1,5 @@
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 004: ID 0e0f:0008 VMware, Inc.
Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub
Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

1
tests/fixtures/centos-7.7/uname.out vendored Normal file
View File

@ -0,0 +1 @@
Linux

10
tests/fixtures/debian10/uname-a.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"kernel_name": "Linux",
"node_name": "debian",
"kernel_release": "5.7.0-2-amd64",
"operating_system": "GNU/Linux",
"processor": "unknown",
"hardware_platform": "unknown",
"machine": "x86_64",
"kernel_version": "#1 SMP Debian 5.7.10-1 (2020-07-26)"
}

2
tests/fixtures/debian10/uname-a.out vendored Normal file
View File

@ -0,0 +1,2 @@
Linux debian 5.7.0-2-amd64 #1 SMP Debian 5.7.10-1 (2020-07-26) x86_64 GNU/Linux

1
tests/fixtures/freebsd12/uname-a.json vendored Normal file
View File

@ -0,0 +1 @@
{"machine":"amd64","kernel_name":"FreeBSD","node_name":"freebsd","kernel_release":"12.1-RELEASE","kernel_version":"FreeBSD 12.1-RELEASE r354233 GENERIC"}

2
tests/fixtures/freebsd12/uname-a.out vendored Normal file
View File

@ -0,0 +1,2 @@
FreeBSD freebsd 12.1-RELEASE FreeBSD 12.1-RELEASE r354233 GENERIC amd64

View File

@ -0,0 +1,7 @@
{
"machine": "amd64",
"kernel_name": "FreeBSD",
"node_name": "freebsd",
"kernel_release": "10.1-RELEASE-p10",
"kernel_version": "FreeBSD 10.1-RELEASE-p10 #0: Wed May 13 06:54:13 UTC 2015 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC"
}

2
tests/fixtures/freebsd12/uname-a2.out vendored Normal file
View File

@ -0,0 +1,2 @@
FreeBSD freebsd 10.1-RELEASE-p10 FreeBSD 10.1-RELEASE-p10 #0: Wed May 13 06:54:13 UTC 2015 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64

File diff suppressed because one or more lines are too long

10001
tests/fixtures/generic/csv-10k-sales-records.csv vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
[{"Name":"Alex","Sex":"M","Age":"41","Height (in)":"74","Weight (lbs)":"170"},{"Name":"Bert","Sex":"M","Age":"42","Height (in)":"68","Weight (lbs)":"166"},{"Name":"Carl","Sex":"M","Age":"32","Height (in)":"70","Weight (lbs)":"155"},{"Name":"Dave","Sex":"M","Age":"39","Height (in)":"72","Weight (lbs)":"167"},{"Name":"Elly","Sex":"F","Age":"30","Height (in)":"66","Weight (lbs)":"124"},{"Name":"Fran","Sex":"F","Age":"33","Height (in)":"66","Weight (lbs)":"115"},{"Name":"Gwen","Sex":"F","Age":"26","Height (in)":"64","Weight (lbs)":"121"},{"Name":"Hank","Sex":"M","Age":"30","Height (in)":"71","Weight (lbs)":"158"},{"Name":"Ivan","Sex":"M","Age":"53","Height (in)":"72","Weight (lbs)":"175"},{"Name":"Jake","Sex":"M","Age":"32","Height (in)":"69","Weight (lbs)":"143"},{"Name":"Kate","Sex":"F","Age":"47","Height (in)":"69","Weight (lbs)":"139"},{"Name":"Luke","Sex":"M","Age":"34","Height (in)":"72","Weight (lbs)":"163"},{"Name":"Myra","Sex":"F","Age":"23","Height (in)":"62","Weight (lbs)":"98"},{"Name":"Neil","Sex":"M","Age":"36","Height (in)":"75","Weight (lbs)":"160"},{"Name":"Omar","Sex":"M","Age":"38","Height (in)":"70","Weight (lbs)":"145"},{"Name":"Page","Sex":"F","Age":"31","Height (in)":"67","Weight (lbs)":"135"},{"Name":"Quin","Sex":"M","Age":"29","Height (in)":"71","Weight (lbs)":"176"},{"Name":"Ruth","Sex":"F","Age":"28","Height (in)":"65","Weight (lbs)":"131"}]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
[{"Year":"1968","Score":"86","Title":"Greetings"},{"Year":"1970","Score":"17","Title":"Bloody Mama"},{"Year":"1970","Score":"73","Title":"Hi, Mom!"},{"Year":"1971","Score":"40","Title":"Born to Win"},{"Year":"1973","Score":"98","Title":"Mean Streets"},{"Year":"1973","Score":"88","Title":"Bang the Drum Slowly"},{"Year":"1974","Score":"97","Title":"The Godfather, Part II"},{"Year":"1976","Score":"41","Title":"The Last Tycoon"},{"Year":"1976","Score":"99","Title":"Taxi Driver"},{"Year":"1977","Score":"47","Title":"1900"},{"Year":"1977","Score":"67","Title":"New York, New York"},{"Year":"1978","Score":"93","Title":"The Deer Hunter"},{"Year":"1980","Score":"97","Title":"Raging Bull"},{"Year":"1981","Score":"75","Title":"True Confessions"},{"Year":"1983","Score":"90","Title":"The King of Comedy"},{"Year":"1984","Score":"89","Title":"Once Upon a Time in America"},{"Year":"1984","Score":"60","Title":"Falling in Love"},{"Year":"1985","Score":"98","Title":"Brazil"},{"Year":"1986","Score":"65","Title":"The Mission"},{"Year":"1987","Score":"100","Title":"Dear America: Letters Home From Vietnam"},{"Year":"1987","Score":"80","Title":"The Untouchables"},{"Year":"1987","Score":"78","Title":"Angel Heart"},{"Year":"1988","Score":"96","Title":"Midnight Run"},{"Year":"1989","Score":"64","Title":"Jacknife"},{"Year":"1989","Score":"47","Title":"We're No Angels"},{"Year":"1990","Score":"88","Title":"Awakenings"},{"Year":"1990","Score":"29","Title":"Stanley & Iris"},{"Year":"1990","Score":"96","Title":"Goodfellas"},{"Year":"1991","Score":"76","Title":"Cape Fear"},{"Year":"1991","Score":"69","Title":"Mistress"},{"Year":"1991","Score":"65","Title":"Guilty by Suspicion"},{"Year":"1991","Score":"71","Title":"Backdraft"},{"Year":"1992","Score":"87","Title":"Thunderheart"},{"Year":"1992","Score":"67","Title":"Night and the City"},{"Year":"1993","Score":"75","Title":"This Boy's Life"},{"Year":"1993","Score":"78","Title":"Mad Dog and Glory"},{"Year":"1993","Score":"96","Title":"A Bronx Tale"},{"Year":"1994","Score":"39","Title":"Mary Shelley's Frankenstein"},{"Year":"1995","Score":"80","Title":"Casino"},{"Year":"1995","Score":"86","Title":"Heat"},{"Year":"1996","Score":"74","Title":"Sleepers"},{"Year":"1996","Score":"38","Title":"The Fan"},{"Year":"1996","Score":"80","Title":"Marvin's Room"},{"Year":"1997","Score":"85","Title":"Wag the Dog"},{"Year":"1997","Score":"87","Title":"Jackie Brown"},{"Year":"1997","Score":"72","Title":"Cop Land"},{"Year":"1998","Score":"68","Title":"Ronin"},{"Year":"1998","Score":"38","Title":"Great Expectations"},{"Year":"1999","Score":"69","Title":"Analyze This"},{"Year":"1999","Score":"43","Title":"Flawless"},{"Year":"2000","Score":"43","Title":"The Adventures of Rocky & Bullwinkle"},{"Year":"2000","Score":"84","Title":"Meet the Parents"},{"Year":"2000","Score":"41","Title":"Men of Honor"},{"Year":"2001","Score":"73","Title":"The Score"},{"Year":"2001","Score":"33","Title":"15 Minutes"},{"Year":"2002","Score":"48","Title":"City by the Sea"},{"Year":"2002","Score":"27","Title":"Analyze That"},{"Year":"2003","Score":"4","Title":"Godsend"},{"Year":"2004","Score":"35","Title":"Shark Tale"},{"Year":"2004","Score":"38","Title":"Meet the Fockers"},{"Year":"2005","Score":"4","Title":"The Bridge of San Luis Rey"},{"Year":"2005","Score":"46","Title":"Rent"},{"Year":"2005","Score":"13","Title":"Hide and Seek"},{"Year":"2006","Score":"54","Title":"The Good Shepherd"},{"Year":"2007","Score":"21","Title":"Arthur and the Invisibles"},{"Year":"2007","Score":"76","Title":"Captain Shakespeare"},{"Year":"2008","Score":"19","Title":"Righteous Kill"},{"Year":"2008","Score":"51","Title":"What Just Happened?"},{"Year":"2009","Score":"46","Title":"Everybody's Fine"},{"Year":"2010","Score":"72","Title":"Machete"},{"Year":"2010","Score":"10","Title":"Little Fockers"},{"Year":"2010","Score":"50","Title":"Stone"},{"Year":"2011","Score":"25","Title":"Killer Elite"},{"Year":"2011","Score":"7","Title":"New Year's Eve"},{"Year":"2011","Score":"70","Title":"Limitless"},{"Year":"2012","Score":"92","Title":"Silver Linings Playbook"},{"Year":"2012","Score":"51","Title":"Being Flynn"},{"Year":"2012","Score":"29","Title":"Red Lights"},{"Year":"2013","Score":"46","Title":"Last Vegas"},{"Year":"2013","Score":"7","Title":"The Big Wedding"},{"Year":"2013","Score":"29","Title":"Grudge Match"},{"Year":"2013","Score":"11","Title":"Killing Season"},{"Year":"2014","Score":"9","Title":"The Bag Man"},{"Year":"2015","Score":"60","Title":"Joy"},{"Year":"2015","Score":"26","Title":"Heist"},{"Year":"2015","Score":"61","Title":"The Intern"},{"Year":"2016","Score":"11","Title":"Dirty Grandpa"}]

View File

@ -0,0 +1 @@
[{"TOK": "JET", "UPDATE": "20031201", "DATE": "20001006", "SHOT": "53521", "TIME": "1.000E+01", "AUXHEAT": "NBIC", "PHASE": "HSELM", "STATE": "TRANS", "PGASA": "2.000E+00", "PGASZ": "1.000E+00", "BGASA": "2", "BGASZ": "1", "BGASA2": "0", "BGASZ2": "0", "PIMPA": "1.658E+01", "PIMPZ": "8.152E+00", "PELLET": "NONE", "RGEO": "2.888E+00", "RMAG": "3.047E+00", "AMIN": "9.807E-01", "SEPLIM": "2.924E-02", "XPLIM": "7.304E-02", "KAPPA": "1.572E+00", "DELTA": "1.781E-01", "INDENT": "0.000E+00", "AREA": "4.572E+00", "VOL": "8.161E+01", "CONFIG": "LSN", "IGRADB": "1", "WALMAT": "IN/C", "DIVMAT": "BE", "LIMMAT": "C/BE", "EVAP": "BE", "BT": "3.598E+00", "IP": "2.000E+06", "VSURF": "1.013E-01", "Q95": "6.001E+00", "BEPMHD": "1.053E+00", "BETMHD": "9.252E-01", "BEPDIA": "1.128E+00", "NEL": "3.106E+19", "DNELDT": "3.106E+19", "ZEFF": "6.612E+00", "PRAD": "4.515E+06", "POHM": "5.122E+04", "ENBI": "1.000E+05", "PINJ": "1.466E+07", "BSOURCE": "771706", "PINJ2": "0.000E+00", "BSOURCE2": "652114", "COCTR": "1.000E+00", "PNBI": "1.420E+07", "ECHFREQ": "-9.999E-09", "ECHMODE": "NONE", "ECHLOC": "NONE", "PECH": "0.000E+00", "ICFREQ": "5.100E+07", "ICSCHEME": "HMIN", "ICANTEN": "MONOPOLE", "PICRH": "4.027E+06", "LHFREQ": "3.700E+09", "LHNPAR": "1.840E+00", "PLH": "2.000E+06", "IBWFREQ": "-9.999E-09", "PIBW": "0.000E+00", "TE0": "9.295E+03", "TI0": "1.373E+04", "WFANI": "6.913E-01", "WFICRH": "7.319E+05", "MEFF": "2.000E+00", "ISEQ": "NONE", "WTH": "3.715E+06", "WTOT": "5.381E+06", "DWTOT": "1.282E+06", "PL": "1.297E+07", "PLTH": "1.210E+07", "TAUTOT": "4.445E-01", "TAUTH": "2.194E-01"}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
[{"Sell":"142","List":"160","Living":"28","Rooms":"10","Beds":"5","Baths":"3","Age":"60","Acres":"0.28","Taxes":"3167"},{"Sell":"175","List":"180","Living":"18","Rooms":"8","Beds":"4","Baths":"1","Age":"12","Acres":"0.43","Taxes":"4033"}]

File diff suppressed because one or more lines are too long

15
tests/fixtures/generic/lsusb-t.out vendored Normal file
View File

@ -0,0 +1,15 @@
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 5000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 2: Dev 90, If 0, Class=Communications, Driver=cdc_acm, 12M
|__ Port 2: Dev 90, If 1, Class=CDC Data, Driver=cdc_acm, 12M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/8p, 480M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M
|__ Port 1: Dev 3, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
|__ Port 2: Dev 4, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
|__ Port 6: Dev 66, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 67, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
|__ Port 1: Dev 67, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M

View File

@ -0,0 +1 @@
[{"bus":"003","device":"090","id":"1915:521a","description":"Nordic Semiconductor ASA nRF52 USB CDC BLE Demo","device_descriptor":{"bLength":{"value":"18"},"bDescriptorType":{"value":"1"},"bcdUSB":{"value":"2.00"},"bDeviceClass":{"value":"0"},"bDeviceSubClass":{"value":"0"},"bDeviceProtocol":{"value":"0","attributes":["call management","use DataInterface"]},"bMaxPacketSize0":{"value":"64"},"idVendor":{"value":"0x1915","description":"Nordic Semiconductor ASA"},"idProduct":{"value":"0x521a"},"bcdDevice":{"value":"1.00"},"iManufacturer":{"value":"1","description":"Nordic Semiconductor"},"iProduct":{"value":"2","description":"nRF52 USB CDC BLE Demo"},"iSerial":{"value":"3","description":"F42DE60BE261"},"bNumConfigurations":{"value":"1"},"configuration_descriptor":{"bLength":{"value":"9"},"bDescriptorType":{"value":"2"},"wTotalLength":{"value":"0x004b"},"bNumInterfaces":{"value":"2","attributes":["call management","use DataInterface"]},"bConfigurationValue":{"value":"1"},"iConfiguration":{"value":"4"},"bmAttributes":{"value":"0xc0","attributes":["Self Powered"]},"MaxPower":{"description":"100mA"},"interface_association":{"bLength":{"value":"8"},"bDescriptorType":{"value":"11"},"bFirstInterface":{"value":"0"},"bInterfaceCount":{"value":"2"},"bFunctionClass":{"value":"2","description":"Communications","attributes":["call management","use DataInterface"]},"bFunctionSubClass":{"value":"2","description":"Abstract (modem)"},"bFunctionProtocol":{"value":"1","description":"AT-commands (v.25ter)"},"iFunction":{"value":"0"}},"interface_descriptors":[{"bLength":{"value":"9"},"bDescriptorType":{"value":"4"},"bInterfaceNumber":{"value":"0"},"bAlternateSetting":{"value":"0","attributes":["call management","use DataInterface"]},"bNumEndpoints":{"value":"1"},"bInterfaceClass":{"value":"2","description":"Communications"},"bInterfaceSubClass":{"value":"2","description":"Abstract (modem)"},"bInterfaceProtocol":{"value":"1","description":"AT-commands (v.25ter)"},"iInterface":{"value":"0"},"cdc_header":{"bcdCDC":{"value":"1.10","attributes":["call management","use DataInterface"]}},"cdc_call_management":{"bmCapabilities":{"value":"0x03","attributes":["call management","use DataInterface"]},"bDataInterface":{"value":"1"}},"cdc_acm":{"bmCapabilities":{"value":"0x02","attributes":["line coding and serial state"]}},"cdc_union":{"bMasterInterface":{"value":"0","attributes":["call management","use DataInterface"]},"bSlaveInterface":{"value":"1","attributes":["call management","use DataInterface"]}},"endpoint_descriptors":[{"bLength":{"value":"7"},"bDescriptorType":{"value":"5"},"bEndpointAddress":{"value":"0x82","description":"EP 2 IN"},"bmAttributes":{"value":"3","attributes":["Transfer Type Interrupt","Synch Type None","Usage Type Data"]},"wMaxPacketSize":{"value":"0x0040","description":"1x 64 bytes"},"bInterval":{"value":"16"}}]},{"bLength":{"value":"9"},"bDescriptorType":{"value":"4"},"bInterfaceNumber":{"value":"1"},"bAlternateSetting":{"value":"0"},"bNumEndpoints":{"value":"2"},"bInterfaceClass":{"value":"10","description":"CDC Data","attributes":["call management","use DataInterface"]},"bInterfaceSubClass":{"value":"0"},"bInterfaceProtocol":{"value":"0"},"iInterface":{"value":"0"},"endpoint_descriptors":[{"bLength":{"value":"7"},"bDescriptorType":{"value":"5"},"bEndpointAddress":{"value":"0x81","description":"EP 1 IN"},"bmAttributes":{"value":"2","attributes":["Transfer Type Bulk","Synch Type None","Usage Type Data"]},"wMaxPacketSize":{"value":"0x0040","description":"1x 64 bytes"},"bInterval":{"value":"0"}},{"bLength":{"value":"7"},"bDescriptorType":{"value":"5"},"bEndpointAddress":{"value":"0x01","description":"EP 1 OUT"},"bmAttributes":{"value":"2","attributes":["Transfer Type Bulk","Synch Type None","Usage Type Data"]},"wMaxPacketSize":{"value":"0x0040","description":"1x 64 bytes"},"bInterval":{"value":"0"}}]}]}}}]

View File

@ -0,0 +1,116 @@
Bus 003 Device 090: ID 1915:521a Nordic Semiconductor ASA nRF52 USB CDC BLE Demo
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
call management
use DataInterface
bMaxPacketSize0 64
idVendor 0x1915 Nordic Semiconductor ASA
idProduct 0x521a
bcdDevice 1.00
iManufacturer 1 Nordic Semiconductor
iProduct 2 nRF52 USB CDC BLE Demo
iSerial 3 F42DE60BE261
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x004b
bNumInterfaces 2
call management
use DataInterface
bConfigurationValue 1
iConfiguration 4
bmAttributes 0xc0
Self Powered
MaxPower 100mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 2 Communications
call management
use DataInterface
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 1 AT-commands (v.25ter)
iFunction 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
call management
use DataInterface
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 0
CDC Header:
bcdCDC 1.10
call management
use DataInterface
CDC Call Management:
bmCapabilities 0x03
call management
use DataInterface
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
call management
use DataInterface
bSlaveInterface 1
call management
use DataInterface
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
call management
use DataInterface
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,348 @@
Bus 002 Device 004: ID 0e0f:0008 VMware, Inc.
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 224 Wireless
bDeviceSubClass 1 Radio Frequency
bDeviceProtocol 1 Bluetooth
bMaxPacketSize0 64
Transfer Type Isochronous
Synch Type None
Usage Type Data
idVendor 0x0e0f VMware, Inc.
idProduct 0x0008
bcdDevice 1.00
iManufacturer 1 VMware
iProduct 2 Virtual Bluetooth Adapter
iSerial 3 000650268328
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 177
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
Transfer Type Isochronous
Synch Type None
Usage Type Data
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
Transfer Type Isochronous
Synch Type None
Usage Type Data
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0000 1x 0 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0000 1x 0 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0009 1x 9 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0009 1x 9 bytes
bInterval 1
Interface Descriptor:
bLength 9
Transfer Type Isochronous
Synch Type None
Usage Type Data
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 2
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0011 1x 17 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0011 1x 17 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 3
Transfer Type Isochronous
Synch Type None
Usage Type Data
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0019 1x 25 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0019 1x 25 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 4
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Transfer Type Isochronous
Synch Type None
Usage Type Data
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0021 1x 33 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0021 1x 33 bytes
bInterval 1
Interface Descriptor:
bLength 9
bDescriptorType 4
Transfer Type Isochronous
Synch Type None
Usage Type Data
bInterfaceNumber 1
bAlternateSetting 5
bNumEndpoints 2
bInterfaceClass 224 Wireless
bInterfaceSubClass 1 Radio Frequency
bInterfaceProtocol 1 Bluetooth
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0031 1x 49 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0031 1x 49 bytes
bInterval 1
Device Status: 0x0001
Self Powered
Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 9 Hub
bDeviceSubClass 0 Unused
bDeviceProtocol 0 Full speed (or root) hub
Transfer Type Isochronous
Synch Type None
Usage Type Data
bMaxPacketSize0 8
idVendor 0x0e0f VMware, Inc.
idProduct 0x0002 Virtual USB Hub
bcdDevice 1.00
iManufacturer 1 VMware, Inc.
iProduct 2 VMware Virtual USB Hub
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 25
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 1 VMware, Inc.
bmAttributes 0xe0
Self Powered
Remote Wakeup
MaxPower 0mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 9 Hub
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0 Full speed (or root) hub
iInterface 1 VMware, Inc.
Transfer Type Isochronous
Synch Type None
Usage Type Data
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0001 1x 1 bytes
bInterval 255
Hub Descriptor:
bLength 9
bDescriptorType 41
nNbrPorts 7
wHubCharacteristic 0x0009
Per-port power switching
Per-port overcurrent protection
bPwrOn2PwrGood 50 * 2 milli seconds
bHubContrCurrent 100 milli Ampere
DeviceRemovable 0x00
PortPwrCtrlMask 0xfe
Hub Port Status:
Port 1: 0000.0103 power enable connect
Port 2: 0000.0100 power
Port 3: 0000.0100 power
Port 4: 0000.0100 power
Port 5: 0000.0100 power
Port 6: 0000.0100 power
Port 7: 0000.0100 power
Device Status: 0x2909
Self Powered

View File

@ -0,0 +1 @@
{"kernel_name":"Linux","node_name":"mymachine","kernel_release":"2.6.18-194.e15PAE","operating_system":"GNU/Linux","processor":"i386","hardware_platform":"i686","machine":"i686","kernel_version":"#1 SMP Fri Apr 2 15:37:44 EDT 2010"}

View File

@ -0,0 +1 @@
Linux mymachine 2.6.18-194.e15PAE #1 SMP Fri Apr 2 15:37:44 EDT 2010 i686 i686 i386 GNU/Linux

1
tests/fixtures/generic/uname-a.json vendored Normal file
View File

@ -0,0 +1 @@
{"kernel_name":"Linux","node_name":"host.example.com","kernel_release":"4.19.0-17-amd64","operating_system":"GNU/Linux","processor":"unknown","hardware_platform":"unknown","machine":"x86_64","kernel_version":"#1 SMP Debian 4.19.194-3 (2021-07-18)"}

2
tests/fixtures/generic/uname-a.out vendored Normal file
View File

@ -0,0 +1,2 @@
Linux host.example.com 4.19.0-17-amd64 #1 SMP Debian 4.19.194-3 (2021-07-18) x86_64 GNU/Linux

1
tests/fixtures/osx-10.14.6/file3.json vendored Normal file

File diff suppressed because one or more lines are too long

72
tests/fixtures/osx-10.14.6/file3.out vendored Normal file
View File

@ -0,0 +1,72 @@
Applications: directory
Desktop: directory
Documents: directory
Downloads: directory
Library: directory
Movies: directory
Music: directory
Pictures: directory
Postman: directory
Public: directory
Virtual Machines.localized: directory
ansible: directory
api: directory
centosserial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
coreosserial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
data.json: UTF-8 Unicode text, with very long lines
fazserial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
fgt1serial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
fgt2serial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
file with colon: in the name: empty
fnditer.py: ASCII text
fortiweb-docker.sh: Bourne-Again shell script text executable, ASCII text
ftmgr.sh: Bourne-Again shell script text executable, ASCII text
git: directory
google-cloud-sdk: directory
ipaddr.json: ASCII text, with very long lines
jc-1.16.0-linux-x86_64.tar.gz: gzip compressed data, last modified: Tue Jul 20 17:32:10 2021, from Unix, original size 93992960
jc-1.16.1-linux-x86_64.tar.gz: gzip compressed data, last modified: Tue Aug 17 20:42:30 2021, from Unix, original size 94033920
jc-1.17.0-linux-x86_64.sha256: ASCII text
jc-1.17.0-linux-x86_64.tar.gz: gzip compressed data, last modified: Sun Sep 26 22:16:00 2021, from Unix, original size 94136320
jc-jq-jp-ps-cpu.gif: GIF image data, version 89a, 1572 x 1212
jc-jq-jp-uptime-small.gif: GIF image data, version 89a, 800 x 617
jc-jq-jp-uptime.gif: GIF image data, version 89a, 1572 x 1212
jcparsers.jlines: ASCII text, with very long lines
jcparsers.json: ASCII text, with very long lines
jello-1.4.0-linux-x86_64.tar.gz: gzip compressed data, last modified: Sat Jun 19 18:19:55 2021, from Unix, original size 92006400
jello-1.4.4-linux-x86_64.tar.gz: gzip compressed data, last modified: Fri Jun 25 08:53:06 2021, from Unix, original size 92016640
jp: Mach-O 64-bit executable x86_64
json-stream.py: Python script text executable, ASCII text
json-stream2.py: Python script text executable, ASCII text
jupyter.sh: ASCII text
kb-fortinet.pem: PEM RSA private key
kelly-aws.pem: PEM RSA private key
kelly-aws2.pem: PEM RSA private key
kellytest.sh: Bourne-Again shell script text executable, ASCII text
kping.out: ASCII text
loadplot.sh: Bourne-Again shell script text executable, ASCII text
ls.jlines: UTF-8 Unicode text, with very long lines
myrecording: data
nse-certs: directory
ping1.out: ASCII text
reading.py: Python script text executable, ASCII text
rpmbuild: directory
scroll.py: Python script text executable, ASCII text
state_test.py: Python script text executable, ASCII text
stream-profiling.xlsx: Microsoft Excel 2007+
test-certs.xls: HTML document text, ISO-8859 text, with very long lines
test-certs.xlsx: Microsoft Excel 2007+
test-output: directory
testcsv.csv: ASCII text, with CR, LF line terminators
testedit.py: Python script text executable, ASCII text
testfile.json: ASCII text
testfile.kb: ASCII text
testfile2.json: ASCII text
tr2dot.py: Python script text executable, ASCII text
traceroute.gv: ASCII text
traceroute.gv.pdf: PDF document, version 1.5
trtwitter.out: ASCII text
twitterdata.jlines: HTML document text, ASCII text, with very long lines
ubuntuserial.sh: Bourne-Again shell script text executable, UTF-8 Unicode text
utils: directory
win32.csv: ASCII text, with CRLF, LF line terminators

146
tests/test_csv_s.py Normal file
View File

@ -0,0 +1,146 @@
import os
import json
import unittest
import jc.parsers.csv_s
from jc.exceptions import ParseError
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
# To create streaming output use:
# $ cat file.csv | jc --csv-s | jello -c > csv-file-streaming.json
class MyTests(unittest.TestCase):
def setUp(self):
# input
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-biostats.csv'), 'r', encoding='utf-8') as f:
self.generic_csv_biostats = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-cities.csv'), 'r', encoding='utf-8') as f:
self.generic_csv_cities = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-deniro.csv'), 'r', encoding='utf-8') as f:
self.generic_csv_deniro = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-example.csv'), 'r', encoding='utf-8') as f:
self.generic_csv_example = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-flyrna.tsv'), 'r', encoding='utf-8') as f:
self.generic_csv_flyrna = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-flyrna2.tsv'), 'r', encoding='utf-8') as f:
self.generic_csv_flyrna2 = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-homes-pipe.csv'), 'r', encoding='utf-8') as f:
self.generic_csv_homes_pipe = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-homes.csv'), 'r', encoding='utf-8') as f:
self.generic_csv_homes = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-10k-sales-records.csv'), 'r', encoding='utf-8') as f:
self.generic_csv_10k_sales_records = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-biostats-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_biostats_streaming_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-cities-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_cities_streaming_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-deniro-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_deniro_streaming_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-example-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_example_streaming_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-flyrna-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_flyrna_streaming_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-flyrna2-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_flyrna2_streaming_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-homes-pipe-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_homes_pipe_streaming_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-homes-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_homes_streaming_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/csv-10k-sales-records-streaming.json'), 'r', encoding='utf-8') as f:
self.generic_csv_10k_sales_records_streaming_json = json.loads(f.read())
def test_csv_s_nodata(self):
"""
Test CSV parser with no data
"""
self.assertEqual(list(jc.parsers.csv_s.parse('', quiet=True)), [])
def test_csv_unparsable(self):
"""
Test CSV streaming parser with '\r' newlines. This will raise ParseError due to a Python bug
that does not correctly iterate on that line ending with sys.stdin. This is not a great test.
https://bugs.python.org/issue45617
"""
data = r'unparsable\rdata' # raw mode simulates unrecognized line separator - not great
g = jc.parsers.csv_s.parse(data.splitlines(), quiet=True)
with self.assertRaises(ParseError):
list(g)
def test_csv_s_biostats(self):
"""
Test 'biostats.csv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_biostats.splitlines(), quiet=True)), self.generic_csv_biostats_streaming_json)
def test_csv_s_cities(self):
"""
Test 'cities.csv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_cities.splitlines(), quiet=True)), self.generic_csv_cities_streaming_json)
def test_csv_s_deniro(self):
"""
Test 'deniro.csv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_deniro.splitlines(), quiet=True)), self.generic_csv_deniro_streaming_json)
def test_csv_s_example(self):
"""
Test 'example.csv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_example.splitlines(), quiet=True)), self.generic_csv_example_streaming_json)
def test_csv_s_flyrna(self):
"""
Test 'flyrna.tsv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_flyrna.splitlines(), quiet=True)), self.generic_csv_flyrna_streaming_json)
def test_csv_s_flyrna2(self):
"""
Test 'flyrna2.tsv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_flyrna2.splitlines(), quiet=True)), self.generic_csv_flyrna2_streaming_json)
def test_csv_s_homes_pipe(self):
"""
Test 'homes-pipe.csv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_homes_pipe.splitlines(), quiet=True)), self.generic_csv_homes_pipe_streaming_json)
def test_csv_s_homes(self):
"""
Test 'homes.csv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_homes.splitlines(), quiet=True)), self.generic_csv_homes_streaming_json)
def test_csv_s_10k_records(self):
"""
Test '10k-sales-records.csv' file
"""
self.assertEqual(list(jc.parsers.csv_s.parse(self.generic_csv_10k_sales_records.splitlines(), quiet=True)), self.generic_csv_10k_sales_records_streaming_json)
if __name__ == '__main__':
unittest.main()

View File

@ -22,6 +22,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/file2.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_file2 = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/file3.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_file3 = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/file.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_file_json = json.loads(f.read())
@ -35,6 +38,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/file2.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_file2_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/file3.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_file3_json = json.loads(f.read())
def test_file_nodata(self):
"""
Test 'file' with no data
@ -65,6 +71,12 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.file.parse(self.osx_10_14_6_file2, quiet=True), self.osx_10_14_6_file2_json)
def test_file3_osx_10_14_6(self):
"""
Test 'file *' with gzip filetpe descriptions including ': ' on OSX 10.14.6
"""
self.assertEqual(jc.parsers.file.parse(self.osx_10_14_6_file3, quiet=True), self.osx_10_14_6_file3_json)
if __name__ == '__main__':
unittest.main()

View File

@ -99,13 +99,13 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ls-l-iso-streaming.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_ls_l_iso_streaming_json = json.loads(f.read())
def test_ls_empty_dir(self):
def test_ls_s_empty_dir(self):
"""
Test plain 'ls' on an empty directory
"""
self.assertEqual(list(jc.parsers.ls_s.parse('', quiet=True)), [])
def test_ls_centos_7_7(self):
def test_ls_s_centos_7_7_raise_exception(self):
"""
Test plain 'ls /' on Centos 7.7 (raises ParseError)
"""
@ -113,67 +113,67 @@ class MyTests(unittest.TestCase):
with self.assertRaises(ParseError):
list(g)
def test_ls_al_centos_7_7(self):
def test_ls_s_al_centos_7_7(self):
"""
Test 'ls -al /' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.centos_7_7_ls_al.splitlines(), quiet=True)), self.centos_7_7_ls_al_streaming_json)
def test_ls_al_ubuntu_18_4(self):
def test_ls_s_al_ubuntu_18_4(self):
"""
Test 'ls -al /' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.ubuntu_18_4_ls_al.splitlines(), quiet=True)), self.ubuntu_18_4_ls_al_streaming_json)
def test_ls_al_osx_10_14_6(self):
def test_ls_s_al_osx_10_14_6(self):
"""
Test 'ls -al /' on OSX 10.14.6
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.osx_10_14_6_ls_al.splitlines(), quiet=True)), self.osx_10_14_6_ls_al_streaming_json)
def test_ls_alh_centos_7_7(self):
def test_ls_s_alh_centos_7_7(self):
"""
Test 'ls -alh /' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.centos_7_7_ls_alh.splitlines(), quiet=True)), self.centos_7_7_ls_alh_streaming_json)
def test_ls_alh_ubuntu_18_4(self):
def test_ls_s_alh_ubuntu_18_4(self):
"""
Test 'ls -alh /' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.ubuntu_18_4_ls_alh.splitlines(), quiet=True)), self.ubuntu_18_4_ls_alh_streaming_json)
def test_ls_alh_osx_10_14_6(self):
def test_ls_s_alh_osx_10_14_6(self):
"""
Test 'ls -alh /' on OSX 10.14.6
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.osx_10_14_6_ls_alh.splitlines(), quiet=True)), self.osx_10_14_6_ls_alh_streaming_json)
def test_ls_alR_centos_7_7(self):
def test_ls_s_alR_centos_7_7(self):
"""
Test 'ls -alR /usr' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.centos_7_7_ls_alR.splitlines(), quiet=True)), self.centos_7_7_ls_alR_streaming_json)
def test_ls_alR_ubuntu_18_4(self):
def test_ls_s_alR_ubuntu_18_4(self):
"""
Test 'ls -alR /usr' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.ubuntu_18_4_ls_alR.splitlines(), quiet=True)), self.ubuntu_18_4_ls_alR_streaming_json)
def test_ls_alR_osx_10_14_6(self):
def test_ls_s_alR_osx_10_14_6(self):
"""
Test 'ls -alR /usr' on OSX 10.14.6
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.osx_10_14_6_ls_alR.splitlines(), quiet=True)), self.osx_10_14_6_ls_alR_streaming_json)
def test_ls_lR_empty_folder_osx_10_14_6(self):
def test_ls_s_lR_empty_folder_osx_10_14_6(self):
"""
Test 'ls -lR' for empty directories on OSX 10.14.6
"""
self.assertEqual(list(jc.parsers.ls_s.parse(self.osx_10_14_6_ls_lR_empty_folder.splitlines(), quiet=True)), self.osx_10_14_6_ls_lR_empty_folder_streaming_json)
def test_ls_l_iso_ubuntu_18_4(self):
def test_ls_s_l_iso_ubuntu_18_4(self):
"""
Test 'ls -l --time-style=full-iso' for files with convertible dates on Ubuntu 18.4
"""

92
tests/test_lsusb.py Normal file
View File

@ -0,0 +1,92 @@
import os
import json
import unittest
import jc.parsers.lsusb
from jc.exceptions import ParseError
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
class MyTests(unittest.TestCase):
def setUp(self):
# input
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/lsusb.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_lsusb = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/lsusb-v.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_lsusb_v = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/lsusb-v-single.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_lsusb_v_single = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/lsusb-test-attributes.out'), 'r', encoding='utf-8') as f:
self.generic_lsusb_test_attributes = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/lsusb-test-attributes2.out'), 'r', encoding='utf-8') as f:
self.generic_lsusb_test_attributes2 = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/lsusb-t.out'), 'r', encoding='utf-8') as f:
self.generic_lsusb_t = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/lsusb.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_lsusb_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/lsusb-v.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_lsusb_v_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/lsusb-v-single.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_lsusb_v_single_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/lsusb-test-attributes.json'), 'r', encoding='utf-8') as f:
self.generic_lsusb_test_attributes_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/lsusb-test-attributes2.json'), 'r', encoding='utf-8') as f:
self.generic_lsusb_test_attributes2_json = json.loads(f.read())
def test_lsusb_nodata(self):
"""
Test 'lsusb' with no data
"""
self.assertEqual(jc.parsers.lsusb.parse('', quiet=True), [])
def test_lsusb_parse_error_generic(self):
"""
Test 'lsusb' with -t option (should raise ParseError)
"""
self.assertRaises(ParseError, jc.parsers.lsusb.parse, self.generic_lsusb_t, quiet=True)
def test_lsusb_centos_7_7(self):
"""
Test 'lsusb' on Centos 7.7
"""
self.assertEqual(jc.parsers.lsusb.parse(self.centos_7_7_lsusb, quiet=True), self.centos_7_7_lsusb_json)
def test_lsusb_v_centos_7_7(self):
"""
Test 'lsusb -v' on Centos 7.7
"""
self.assertEqual(jc.parsers.lsusb.parse(self.centos_7_7_lsusb_v, quiet=True), self.centos_7_7_lsusb_v_json)
def test_lsusb_v_single_centos_7_7(self):
"""
Test 'lsusb -v' with different hardware
"""
self.assertEqual(jc.parsers.lsusb.parse(self.centos_7_7_lsusb_v_single, quiet=True), self.centos_7_7_lsusb_v_single_json)
def test_lsusb_test_attributes_generic(self):
"""
Test 'lsusb -v' with stress test attributes
"""
self.assertEqual(jc.parsers.lsusb.parse(self.generic_lsusb_test_attributes, quiet=True), self.generic_lsusb_test_attributes_json)
def test_lsusb_test_attributes2_generic(self):
"""
Test 'lsusb -v' with stress test attributes 2
"""
self.assertEqual(jc.parsers.lsusb.parse(self.generic_lsusb_test_attributes2, quiet=True), self.generic_lsusb_test_attributes2_json)
if __name__ == '__main__':
unittest.main()

View File

@ -393,19 +393,25 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/pi/ping-ip-O-D-streaming.json'), 'r', encoding='utf-8') as f:
self.pi_ping_ip_O_D_streaming_json = json.loads(f.read())
def test_ping_nodata(self):
def test_ping_s_nodata(self):
"""
Test 'ping' with no data
"""
self.assertEqual(list(jc.parsers.ping_s.parse('')), [])
self.assertEqual(list(jc.parsers.ping_s.parse('', quiet=True)), [])
def test_ping_ignore_exceptions_success(self):
def test_ping_s_unparsable(self):
data = 'unparsable data'
g = jc.parsers.ping_s.parse(data.splitlines(), quiet=True)
with self.assertRaises(ParseError):
list(g)
def test_ping_s_ignore_exceptions_success(self):
"""
Test 'ping' with -qq (ignore_exceptions) option
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping_ip_O.splitlines(), quiet=True, ignore_exceptions=True)), self.centos_7_7_ping_ip_O_streaming_ignore_exceptions_json)
def test_ping_ignore_exceptions_error(self):
def test_ping_s_ignore_exceptions_error(self):
"""
Test 'ping' with -qq (ignore_exceptions) option option and error
"""
@ -413,43 +419,43 @@ class MyTests(unittest.TestCase):
expected = json.loads('[{"_jc_meta":{"success":false,"error":"ParseError: Could not detect ping OS","line":"not ping"}}]')
self.assertEqual(list(jc.parsers.ping_s.parse(data_in.splitlines(), quiet=True, ignore_exceptions=True)), expected)
def test_ping_ip_O_centos_7_7(self):
def test_ping_s_ip_O_centos_7_7(self):
"""
Test 'ping <ip> -O' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping_ip_O.splitlines(), quiet=True)), self.centos_7_7_ping_ip_O_streaming_json)
def test_ping_ip_O_D_centos_7_7(self):
def test_ping_s_ip_O_D_centos_7_7(self):
"""
Test 'ping <ip> -O -D' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping_ip_O_D.splitlines(), quiet=True)), self.centos_7_7_ping_ip_O_D_streaming_json)
def test_ping_hostname_O_centos_7_7(self):
def test_ping_s_hostname_O_centos_7_7(self):
"""
Test 'ping <hostname> -O' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping_hostname_O.splitlines(), quiet=True)), self.centos_7_7_ping_hostname_O_streaming_json)
def test_ping_hostname_O_p_centos_7_7(self):
def test_ping_s_hostname_O_p_centos_7_7(self):
"""
Test 'ping <hostname> -O -p' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping_hostname_O_p.splitlines(), quiet=True)), self.centos_7_7_ping_hostname_O_p_streaming_json)
def test_ping_hostname_O_D_p_s_centos_7_7(self):
def test_ping_s_hostname_O_D_p_s_centos_7_7(self):
"""
Test 'ping <hostname> -O -D -p -s' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping_hostname_O_D_p_s.splitlines(), quiet=True)), self.centos_7_7_ping_hostname_O_D_p_s_streaming_json)
def test_ping6_ip_O_p_centos_7_7(self):
def test_ping6_s_ip_O_p_centos_7_7(self):
"""
Test 'ping6 <ip> -O -p' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping6_ip_O_p.splitlines(), quiet=True)), self.centos_7_7_ping6_ip_O_p_streaming_json)
def test_ping6_ip_O_p_unparsable_centos_7_7(self):
def test_ping6_s_ip_O_p_unparsable_centos_7_7(self):
"""
Test 'ping6 <ip> -O -p' with unparsable lines on Centos 7.7 (raises IndexError)
"""
@ -457,37 +463,37 @@ class MyTests(unittest.TestCase):
with self.assertRaises(IndexError):
list(g)
def test_ping6_ip_O_D_p_centos_7_7(self):
def test_ping6_s_ip_O_D_p_centos_7_7(self):
"""
Test 'ping6 <ip> -O -D -p' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping6_ip_O_D_p.splitlines(), quiet=True)), self.centos_7_7_ping6_ip_O_D_p_streaming_json)
def test_ping6_hostname_O_p_centos_7_7(self):
def test_ping6_s_hostname_O_p_centos_7_7(self):
"""
Test 'ping6 <hostname> -O -p' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping6_hostname_O_p.splitlines(), quiet=True)), self.centos_7_7_ping6_hostname_O_p_streaming_json)
def test_ping6_hostname_O_D_p_s_centos_7_7(self):
def test_ping6_s_hostname_O_D_p_s_centos_7_7(self):
"""
Test 'ping6 <hostname> -O -D -p -s' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping6_hostname_O_D_p_s.splitlines(), quiet=True)), self.centos_7_7_ping6_hostname_O_D_p_s_streaming_json)
def test_ping_ip_dup_centos_7_7(self):
def test_ping_s_ip_dup_centos_7_7(self):
"""
Test 'ping <ip>' to broadcast IP to get duplicate replies on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping_ip_dup.splitlines(), quiet=True)), self.centos_7_7_ping_ip_dup_streaming_json)
def test_ping6_ip_dup_centos_7_7(self):
def test_ping6_s_ip_dup_centos_7_7(self):
"""
Test 'ping6 <ip>' to broadcast IP to get duplicate replies on Centos 7.7
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.centos_7_7_ping6_ip_dup.splitlines(), quiet=True)), self.centos_7_7_ping6_ip_dup_streaming_json)
def test_ping_ip_O_unparsedlines_centos_7_7(self):
def test_ping_s_ip_O_unparsedlines_centos_7_7(self):
"""
Test 'ping <ip> -O' on Centos 7.7 with unparsable lines and error messages
"""
@ -495,229 +501,229 @@ class MyTests(unittest.TestCase):
with self.assertRaises(IndexError):
list(g)
def test_ping_ip_O_ubuntu_18_4(self):
def test_ping_s_ip_O_ubuntu_18_4(self):
"""
Test 'ping <ip> -O' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping_ip_O.splitlines(), quiet=True)), self.ubuntu_18_4_ping_ip_O_streaming_json)
def test_ping_ip_O_D_ubuntu_18_4(self):
def test_ping_s_ip_O_D_ubuntu_18_4(self):
"""
Test 'ping <ip> -O -D' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping_ip_O_D.splitlines(), quiet=True)), self.ubuntu_18_4_ping_ip_O_D_streaming_json)
def test_ping_hostname_O_ubuntu_18_4(self):
def test_ping_s_hostname_O_ubuntu_18_4(self):
"""
Test 'ping <hostname> -O' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping_hostname_O.splitlines(), quiet=True)), self.ubuntu_18_4_ping_hostname_O_streaming_json)
def test_ping_hostname_O_p_ubuntu_18_4(self):
def test_ping_s_hostname_O_p_ubuntu_18_4(self):
"""
Test 'ping <hostname> -O -p' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping_hostname_O_p.splitlines(), quiet=True)), self.ubuntu_18_4_ping_hostname_O_p_streaming_json)
def test_ping_hostname_O_D_p_s_ubuntu_18_4(self):
def test_ping_s_hostname_O_D_p_s_ubuntu_18_4(self):
"""
Test 'ping <hostname> -O -D -p -s' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping_hostname_O_D_p_s.splitlines(), quiet=True)), self.ubuntu_18_4_ping_hostname_O_D_p_s_streaming_json)
def test_ping6_ip_O_p_ubuntu_18_4(self):
def test_ping6_s_ip_O_p_ubuntu_18_4(self):
"""
Test 'ping6 <ip> -O -p' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping6_ip_O_p.splitlines(), quiet=True)), self.ubuntu_18_4_ping6_ip_O_p_streaming_json)
def test_ping6_ip_O_D_p_ubuntu_18_4(self):
def test_ping6_s_ip_O_D_p_ubuntu_18_4(self):
"""
Test 'ping6 <ip> -O -D -p' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping6_ip_O_D_p.splitlines(), quiet=True)), self.ubuntu_18_4_ping6_ip_O_D_p_streaming_json)
def test_ping6_hostname_O_p_ubuntu_18_4(self):
def test_ping6_s_hostname_O_p_ubuntu_18_4(self):
"""
Test 'ping6 <hostname> -O -p' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping6_hostname_O_p.splitlines(), quiet=True)), self.ubuntu_18_4_ping6_hostname_O_p_streaming_json)
def test_ping6_hostname_O_D_p_s_ubuntu_18_4(self):
def test_ping6_s_hostname_O_D_p_s_ubuntu_18_4(self):
"""
Test 'ping6 <hostname> -O -D -p -s' on Ubuntu 18.4
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_18_4_ping6_hostname_O_D_p_s.splitlines(), quiet=True)), self.ubuntu_18_4_ping6_hostname_O_D_p_s_streaming_json)
def test_ping_ip_O_fedora32(self):
def test_ping_s_ip_O_fedora32(self):
"""
Test 'ping <ip> -O' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping_ip_O.splitlines(), quiet=True)), self.fedora32_ping_ip_O_streaming_json)
def test_ping_ip_O_D_fedora32(self):
def test_ping_s_ip_O_D_fedora32(self):
"""
Test 'ping <ip> -O -D' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping_ip_O_D.splitlines(), quiet=True)), self.fedora32_ping_ip_O_D_streaming_json)
def test_ping_hostname_O_fedora32(self):
def test_ping_s_hostname_O_fedora32(self):
"""
Test 'ping <hostname> -O' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping_hostname_O.splitlines(), quiet=True)), self.fedora32_ping_hostname_O_streaming_json)
def test_ping_hostname_O_p_fedora32(self):
def test_ping_s_hostname_O_p_fedora32(self):
"""
Test 'ping <hostname> -O -p' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping_hostname_O_p.splitlines(), quiet=True)), self.fedora32_ping_hostname_O_p_streaming_json)
def test_ping_hostname_O_D_p_s_fedora32(self):
def test_ping_s_hostname_O_D_p_s_fedora32(self):
"""
Test 'ping <hostname> -O -D -p -s' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping_hostname_O_D_p_s.splitlines(), quiet=True)), self.fedora32_ping_hostname_O_D_p_s_streaming_json)
def test_ping6_ip_O_p_fedora32(self):
def test_ping6_s_ip_O_p_fedora32(self):
"""
Test 'ping6 <ip> -O -p' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping6_ip_O_p.splitlines(), quiet=True)), self.fedora32_ping6_ip_O_p_streaming_json)
def test_ping6_ip_O_D_p_fedora32(self):
def test_ping6_s_ip_O_D_p_fedora32(self):
"""
Test 'ping6 <ip> -O -D -p' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping6_ip_O_D_p.splitlines(), quiet=True)), self.fedora32_ping6_ip_O_D_p_streaming_json)
def test_ping6_hostname_O_p_fedora32(self):
def test_ping6_s_hostname_O_p_fedora32(self):
"""
Test 'ping6 <hostname> -O -p' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping6_hostname_O_p.splitlines(), quiet=True)), self.fedora32_ping6_hostname_O_p_streaming_json)
def test_ping6_hostname_O_D_p_s_fedora32(self):
def test_ping6_s_hostname_O_D_p_s_fedora32(self):
"""
Test 'ping6 <hostname> -O -D -p -s' on fedora32
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.fedora32_ping6_hostname_O_D_p_s.splitlines(), quiet=True)), self.fedora32_ping6_hostname_O_D_p_s_streaming_json)
def test_ping_hostname_p_freebsd12(self):
def test_ping_s_hostname_p_freebsd12(self):
"""
Test 'ping <hostname> -p' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping_hostname_p.splitlines(), quiet=True)), self.freebsd12_ping_hostname_p_streaming_json)
def test_ping_hostname_s_freebsd12(self):
def test_ping_s_hostname_s_freebsd12(self):
"""
Test 'ping <hostname> -s' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping_hostname_s.splitlines(), quiet=True)), self.freebsd12_ping_hostname_s_streaming_json)
def test_ping_ping_hostname_freebsd12(self):
def test_ping_s_ping_hostname_freebsd12(self):
"""
Test 'ping <hostname>' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping_hostname.splitlines(), quiet=True)), self.freebsd12_ping_hostname_streaming_json)
def test_ping_ip_p_freebsd12(self):
def test_ping_s_ip_p_freebsd12(self):
"""
Test 'ping <ip> -p' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping_ip_p.splitlines(), quiet=True)), self.freebsd12_ping_ip_p_streaming_json)
def test_ping_ip_s_freebsd12(self):
def test_ping_s_ip_s_freebsd12(self):
"""
Test 'ping <ip> -s' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping_ip_s.splitlines(), quiet=True)), self.freebsd12_ping_ip_s_streaming_json)
def test_ping_ip_freebsd12(self):
def test_ping_s_ip_freebsd12(self):
"""
Test 'ping6 <ip>' on freebsd127
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping_ip.splitlines(), quiet=True)), self.freebsd12_ping_ip_streaming_json)
def test_ping6_hostname_p_freebsd12(self):
def test_ping6_s_hostname_p_freebsd12(self):
"""
Test 'ping6 <hostname> -p' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping6_hostname_p.splitlines(), quiet=True)), self.freebsd12_ping6_hostname_p_streaming_json)
def test_ping6_hostname_s_freebsd12(self):
def test_ping6_s_hostname_s_freebsd12(self):
"""
Test 'ping6 <hostname> -s' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping6_hostname_s.splitlines(), quiet=True)), self.freebsd12_ping6_hostname_s_streaming_json)
def test_ping6_hostname_freebsd12(self):
def test_ping6_s_hostname_freebsd12(self):
"""
Test 'ping6 <hostname>' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping6_hostname.splitlines(), quiet=True)), self.freebsd12_ping6_hostname_streaming_json)
def test_ping6_ip_p_freebsd12(self):
def test_ping6_s_ip_p_freebsd12(self):
"""
Test 'ping6 <ip> -p' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping6_ip_p.splitlines(), quiet=True)), self.freebsd12_ping6_ip_p_streaming_json)
def test_ping6_ip_s_freebsd12(self):
def test_ping6_s_ip_s_freebsd12(self):
"""
Test 'ping6 <ip> -s' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping6_ip_s.splitlines(), quiet=True)), self.freebsd12_ping6_ip_s_streaming_json)
def test_ping6_ip_freebsd12(self):
def test_ping6_s_ip_freebsd12(self):
"""
Test 'ping6 <ip>' on freebsd12
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.freebsd12_ping6_ip.splitlines(), quiet=True)), self.freebsd12_ping6_ip_streaming_json)
def test_ping_hostname_p_osx_10_14_6(self):
def test_ping_s_hostname_p_osx_10_14_6(self):
"""
Test 'ping <hostname> -p' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping_hostname_p.splitlines(), quiet=True)), self.osx_10_14_6_ping_hostname_p_streaming_json)
def test_ping_hostname_s_osx_10_14_6(self):
def test_ping_s_hostname_s_osx_10_14_6(self):
"""
Test 'ping <hostname> -s' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping_hostname_s.splitlines(), quiet=True)), self.osx_10_14_6_ping_hostname_s_streaming_json)
def test_ping_hostname_osx_10_14_6(self):
def test_ping_s_hostname_osx_10_14_6(self):
"""
Test 'ping <hostname>' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping_hostname.splitlines(), quiet=True)), self.osx_10_14_6_ping_hostname_streaming_json)
def test_ping_ip_p_osx_10_14_6(self):
def test_ping_s_ip_p_osx_10_14_6(self):
"""
Test 'ping <ip> -p' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping_ip_p.splitlines(), quiet=True)), self.osx_10_14_6_ping_ip_p_streaming_json)
def test_ping_ip_s_osx_10_14_6(self):
def test_ping_s_ip_s_osx_10_14_6(self):
"""
Test 'ping <ip> -s' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping_ip_s.splitlines(), quiet=True)), self.osx_10_14_6_ping_ip_s_streaming_json)
def test_ping_ip_osx_10_14_6(self):
def test_ping_s_ip_osx_10_14_6(self):
"""
Test 'ping <ip>' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping_ip.splitlines(), quiet=True)), self.osx_10_14_6_ping_ip_streaming_json)
def test_ping_ip_unreachable_osx_10_14_6(self):
def test_ping_s_ip_unreachable_osx_10_14_6(self):
"""
Test 'ping <ip>' with host unreachable error on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping_ip_unreachable.splitlines(), quiet=True)), self.osx_10_14_6_ping_ip_unreachable_streaming_json)
def test_ping_ip_unknown_errors_osx_10_14_6(self):
def test_ping_s_ip_unknown_errors_osx_10_14_6(self):
"""
Test 'ping <ip>' with unknown/unparsable errors on osx 10.14.6
"""
@ -725,43 +731,43 @@ class MyTests(unittest.TestCase):
with self.assertRaises(IndexError):
list(g)
def test_ping6_hostname_p_osx_10_14_6(self):
def test_ping6_s_hostname_p_osx_10_14_6(self):
"""
Test 'ping6 <hostname> -p' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping6_hostname_p.splitlines(), quiet=True)), self.osx_10_14_6_ping6_hostname_p_streaming_json)
def test_ping6_hostname_s_osx_10_14_6(self):
def test_ping6_s_hostname_s_osx_10_14_6(self):
"""
Test 'ping6 <hostname> -s' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping6_hostname_s.splitlines(), quiet=True)), self.osx_10_14_6_ping6_hostname_s_streaming_json)
def test_ping6_hostname_osx_10_14_6(self):
def test_ping6_s_hostname_osx_10_14_6(self):
"""
Test 'ping6 <hostname>' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping6_hostname.splitlines(), quiet=True)), self.osx_10_14_6_ping6_hostname_streaming_json)
def test_ping6_ip_p_osx_10_14_6(self):
def test_ping6_s_ip_p_osx_10_14_6(self):
"""
Test 'ping6 <ip> -p' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping6_ip_p.splitlines(), quiet=True)), self.osx_10_14_6_ping6_ip_p_streaming_json)
def test_ping6_ip_s_osx_10_14_6(self):
def test_ping6_s_ip_s_osx_10_14_6(self):
"""
Test 'ping6 <ip> -s' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping6_ip_s.splitlines(), quiet=True)), self.osx_10_14_6_ping6_ip_s_streaming_json)
def test_ping6_ip_osx_10_14_6(self):
def test_ping6_s_ip_osx_10_14_6(self):
"""
Test 'ping6 <ip>' on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping6_ip.splitlines(), quiet=True)), self.osx_10_14_6_ping6_ip_streaming_json)
def test_ping6_ip_unparsable_osx_10_14_6(self):
def test_ping6_s_ip_unparsable_osx_10_14_6(self):
"""
Test 'ping6 <ip>' with unparsable lines on osx 10.14.6
"""
@ -769,25 +775,25 @@ class MyTests(unittest.TestCase):
with self.assertRaises(IndexError):
list(g)
def test_ping_ip_dup_osx_10_14_6(self):
def test_ping_s_ip_dup_osx_10_14_6(self):
"""
Test 'ping <ip>' to broadcast IP to get duplicate replies on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping_ip_dup.splitlines(), quiet=True)), self.osx_10_14_6_ping_ip_dup_streaming_json)
def test_ping6_ip_dup_osx_10_14_6(self):
def test_ping6_s_ip_dup_osx_10_14_6(self):
"""
Test 'ping6 <ip>' to broadcast IP to get duplicate replies on osx 10.14.6
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.osx_10_14_6_ping6_ip_dup.splitlines(), quiet=True)), self.osx_10_14_6_ping6_ip_dup_streaming_json)
def test_ping_ip_O_pi(self):
def test_ping_s_ip_O_pi(self):
"""
Test 'ping6 <ip> -O' on raspberry pi
"""
self.assertEqual(list(jc.parsers.ping_s.parse(self.pi_ping_ip_O.splitlines(), quiet=True)), self.pi_ping_ip_O_streaming_json)
def test_ping_ip_O_D_pi(self):
def test_ping_s_ip_O_D_pi(self):
"""
Test 'ping6 <ip> -O -D' on raspberry pi
"""

View File

@ -2,6 +2,7 @@ import os
import json
import unittest
import jc.parsers.uname
from jc.exceptions import ParseError
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
@ -13,6 +14,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/uname-a.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_uname_a = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/uname.out'), 'r', encoding='utf-8') as f:
self.centos_7_7_uname = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/uname-a.out'), 'r', encoding='utf-8') as f:
self.ubuntu_18_4_uname_a = f.read()
@ -25,6 +29,21 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/uname.out'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_uname = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/uname-a.out'), 'r', encoding='utf-8') as f:
self.freebsd12_uname_a = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/uname-a2.out'), 'r', encoding='utf-8') as f:
self.freebsd12_uname_a2 = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/uname-a.out'), 'r', encoding='utf-8') as f:
self.generic_uname_a = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/uname-a-different-proc.out'), 'r', encoding='utf-8') as f:
self.generic_uname_a_different_proc = f.read()
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/debian10/uname-a.out'), 'r', encoding='utf-8') as f:
self.debian_10_uname_a = f.read()
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/uname-a.json'), 'r', encoding='utf-8') as f:
self.centos_7_7_uname_a_json = json.loads(f.read())
@ -38,17 +57,38 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/osx-10.14.6/uname-a.json'), 'r', encoding='utf-8') as f:
self.osx_10_14_6_uname_a_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/uname-a.json'), 'r', encoding='utf-8') as f:
self.freebsd12_uname_a_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/freebsd12/uname-a2.json'), 'r', encoding='utf-8') as f:
self.freebsd12_uname_a2_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/uname-a.json'), 'r', encoding='utf-8') as f:
self.generic_uname_a_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/uname-a-different-proc.json'), 'r', encoding='utf-8') as f:
self.generic_uname_a_different_proc_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/debian10/uname-a.json'), 'r', encoding='utf-8') as f:
self.debian_10_uname_a_json = json.loads(f.read())
def test_uname_nodata(self):
"""
Test 'uname -a' with no data
"""
self.assertEqual(jc.parsers.uname.parse('', quiet=True), {})
def test_uname_no_a(self):
def test_uname_no_a_osx(self):
"""
Test 'uname' without -a option. Should generate a ParseError exception
Test 'uname' without -a option on OSX. Should generate a ParseError exception
"""
self.assertRaises(jc.parsers.uname.ParseError, jc.parsers.uname.parse, self.osx_10_14_6_uname)
self.assertRaises(ParseError, jc.parsers.uname.parse, self.osx_10_14_6_uname, quiet=True)
def test_uname_no_a_centos(self):
"""
Test 'uname' without -a option on Centos. Should generate a ParseError exception
"""
self.assertRaises(ParseError, jc.parsers.uname.parse, self.centos_7_7_uname, quiet=True)
def test_uname_centos_7_7(self):
"""
@ -74,6 +114,36 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.uname.parse(self.osx_10_14_6_uname_a, quiet=True), self.osx_10_14_6_uname_a_json)
def test_uname_freebsd12(self):
"""
Test 'uname -a' on freebsd12
"""
self.assertEqual(jc.parsers.uname.parse(self.freebsd12_uname_a, quiet=True), self.freebsd12_uname_a_json)
def test_uname2_freebsd12(self):
"""
Test 'uname -a' on freebsd12 with longer version level string
"""
self.assertEqual(jc.parsers.uname.parse(self.freebsd12_uname_a2, quiet=True), self.freebsd12_uname_a2_json)
def test_uname_generic(self):
"""
Test 'uname -a' on debian with missing hardware platform and processor
"""
self.assertEqual(jc.parsers.uname.parse(self.generic_uname_a, quiet=True), self.generic_uname_a_json)
def test_uname_different_proc_generic(self):
"""
Test 'uname -a' on machine with different processor type
"""
self.assertEqual(jc.parsers.uname.parse(self.generic_uname_a_different_proc, quiet=True), self.generic_uname_a_different_proc_json)
def test_uname_debian_10(self):
"""
Test 'uname -a' on debian 10 with missing hardware platform and processor
"""
self.assertEqual(jc.parsers.uname.parse(self.debian_10_uname_a, quiet=True), self.debian_10_uname_a_json)
if __name__ == '__main__':
unittest.main()

View File

@ -48,6 +48,10 @@ class MyTests(unittest.TestCase):
'2019-08-13 18:13:43.555604315 -0400': {'string': '2019-08-13 18:13:43.555604315 -0400', 'format': 7200, 'naive': 1565745223, 'utc': None},
# C local format (found in stat cli output - linux) UTC
'2019-08-13 18:13:43.555604315 -0000': {'string': '2019-08-13 18:13:43.555604315 -0000', 'format': 7200, 'naive': 1565745223, 'utc': 1565720023},
# C locale format with non-UTC tz (found in modified vmstat cli output)
'2021-09-16 20:32:28 PDT': {'string': '2021-09-16 20:32:28 PDT', 'format': 7250, 'naive': 1631849548, 'utc': None},
# C locale format (found in modified vmstat cli output)
'2021-09-16 20:32:28 UTC': {'string': '2021-09-16 20:32:28 UTC', 'format': 7255, 'naive': 1631849548, 'utc': 1631824348},
# C locale format (found in timedatectl cli output)
'Wed 2020-03-11 00:53:21 UTC': {'string': 'Wed 2020-03-11 00:53:21 UTC', 'format': 7300, 'naive': 1583913201, 'utc': 1583888001},
# test with None input

View File

@ -15,7 +15,7 @@ if not sys.platform.startswith('win32'):
# To create streaming output use:
# $ cat vmstat.out | jc --ls-s | jello -c > vmstat-streaming.json
# $ cat vmstat.out | jc --vmstat-s | jello -c > vmstat-streaming.json
class MyTests(unittest.TestCase):
@ -71,65 +71,66 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/vmstat-1-long-streaming.json'), 'r', encoding='utf-8') as f:
self.ubuntu_18_04_vmstat_1_long_streaming_json = json.loads(f.read())
def test_vmstat_nodata(self):
def test_vmstat_s_nodata(self):
"""
Test 'vmstat' with no data
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse('', quiet=True)), [])
def test_vmstat_unparsable(self):
def test_vmstat_s_unparsable(self):
data = 'unparsable data'
g = jc.parsers.vmstat_s.parse(data.splitlines(), quiet=True)
with self.assertRaises(ParseError):
list(g)
def test_vmstat_centos_7_7(self):
def test_vmstat_s_centos_7_7(self):
"""
Test 'vmstat' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse(self.centos_7_7_vmstat.splitlines(), quiet=True)), self.centos_7_7_vmstat_streaming_json)
def test_vmstat_a_centos_7_7(self):
def test_vmstat_s_a_centos_7_7(self):
"""
Test 'vmstat -a' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse(self.centos_7_7_vmstat_a.splitlines(), quiet=True)), self.centos_7_7_vmstat_a_streaming_json)
def test_vmstat_w_centos_7_7(self):
def test_vmstat_s_w_centos_7_7(self):
"""
Test 'vmstat -w' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse(self.centos_7_7_vmstat_w.splitlines(), quiet=True)), self.centos_7_7_vmstat_w_streaming_json)
def test_vmstat_at_5_10_centos_7_7(self):
def test_vmstat_s_at_5_10_centos_7_7(self):
"""
Test 'vmstat -at 5 10' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse(self.centos_7_7_vmstat_at_5_10.splitlines(), quiet=True)), self.centos_7_7_vmstat_at_5_10_streaming_json)
def test_vmstat_awt_centos_7_7(self):
def test_vmstat_s_awt_centos_7_7(self):
"""
Test 'vmstat -awt' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse(self.centos_7_7_vmstat_awt.splitlines(), quiet=True)), self.centos_7_7_vmstat_awt_streaming_json)
def test_vmstat_d_centos_7_7(self):
def test_vmstat_s_d_centos_7_7(self):
"""
Test 'vmstat -d' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse(self.centos_7_7_vmstat_d.splitlines(), quiet=True)), self.centos_7_7_vmstat_d_streaming_json)
def test_vmstat_dt_centos_7_7(self):
def test_vmstat_s_dt_centos_7_7(self):
"""
Test 'vmstat -dt' on Centos 7.7
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse(self.centos_7_7_vmstat_dt.splitlines(), quiet=True)), self.centos_7_7_vmstat_dt_streaming_json)
def test_vmstat_1_long_ubuntu_18_04(self):
def test_vmstat_s_1_long_ubuntu_18_04(self):
"""
Test 'vmstat -1' (on ubuntu) with long output that reprints the header rows
"""
self.assertEqual(list(jc.parsers.vmstat_s.parse(self.ubuntu_18_04_vmstat_1_long.splitlines(), quiet=True)), self.ubuntu_18_04_vmstat_1_long_streaming_json)
if __name__ == '__main__':
unittest.main()