diff --git a/CHANGELOG b/CHANGELOG
index 3d5645f6..d2aecd5e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,19 @@
jc changelog
+20231021 v1.23.5
+- Add `host` command parser
+- Add `nsd-control` command parser
+- Add `lsb_release` command parser
+- Add `/etc/os-release` file parser
+- Enhance `env` command parser to support multi-line values
+- Enhance `ping` and `ping-s` parsers to add error and corrupted support
+- Enhance `xml` parser to include comments in the JSON output
+- Fix `pidstat` command parser when using `-T ALL`
+- Fix `x509-cert` parser to allow negative serial numbers
+- Fix `x509-cert` parser for cases when bitstrings are larger than standard
+- Fix `xrandr` command parser for associated device issues
+- Fix error when pygments library is not installed
+
20230730 v1.23.4
- Add `/etc/resolve.conf` file parser
- Add `/proc/net/tcp` and `/proc/net/tcp6` file parser
diff --git a/README.md b/README.md
index dfa0ddf6..ffe0b816 100644
--- a/README.md
+++ b/README.md
@@ -202,6 +202,7 @@ option.
| `--hashsum` | hashsum command parser (`md5sum`, `shasum`, etc.) | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hashsum) |
| `--hciconfig` | `hciconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hciconfig) |
| `--history` | `history` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/history) |
+| `--host` | `host` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/host) |
| `--hosts` | `/etc/hosts` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/hosts) |
| `--id` | `id` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/id) |
| `--ifconfig` | `ifconfig` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ifconfig) |
@@ -222,6 +223,7 @@ option.
| `--ls` | `ls` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ls) |
| `--ls-s` | `ls` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ls_s) |
| `--lsattr` | `lsattr` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsattr) |
+| `--lsb-release` | `lsb_release` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsb_release) |
| `--lsblk` | `lsblk` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk) |
| `--lsmod` | `lsmod` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod) |
| `--lsof` | `lsof` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof) |
@@ -234,9 +236,11 @@ option.
| `--mpstat-s` | `mpstat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s) |
| `--netstat` | `netstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat) |
| `--nmcli` | `nmcli` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli) |
+| `--nsd-control` | `nsd-control` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/nsd_control) |
| `--ntpq` | `ntpq -p` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq) |
| `--openvpn` | openvpn-status.log file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/openvpn) |
| `--os-prober` | `os-prober` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/os_prober) |
+| `--os-release` | `/etc/os-release` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/os_release) |
| `--passwd` | `/etc/passwd` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/passwd) |
| `--pci-ids` | `pci.ids` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pci_ids) |
| `--pgpass` | PostgreSQL password file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/pgpass) |
diff --git a/completions/jc_bash_completion.sh b/completions/jc_bash_completion.sh
index 2c02ac30..35ab01d0 100644
--- a/completions/jc_bash_completion.sh
+++ b/completions/jc_bash_completion.sh
@@ -3,8 +3,8 @@ _jc()
local cur prev words cword jc_commands jc_parsers jc_options \
jc_about_options jc_about_mod_options jc_help_options jc_special_options
- jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat ip iptables iw iwconfig jobs last lastb ls lsattr lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool)
- jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
+ jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig host id ifconfig iostat ip iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli nsd-control ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool)
+ jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --unbuffer -u --yaml-out -y)
jc_about_options=(--about -a)
jc_about_mod_options=(--pretty -p --yaml-out -y --monochrome -m --force-color -C)
diff --git a/completions/jc_zsh_completion.sh b/completions/jc_zsh_completion.sh
index 0625204d..eedc3453 100644
--- a/completions/jc_zsh_completion.sh
+++ b/completions/jc_zsh_completion.sh
@@ -9,7 +9,7 @@ _jc() {
jc_help_options jc_help_options_describe \
jc_special_options jc_special_options_describe
- jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig id ifconfig iostat ip iptables iw iwconfig jobs last lastb ls lsattr lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool)
+ jc_commands=(acpi airport arp blkid bluetoothctl cbt certbot chage cksum crontab date df dig dmidecode dpkg du env file findmnt finger free git gpg hciconfig host id ifconfig iostat ip iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat netstat nmcli nsd-control ntpq os-prober pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc who xrandr zipinfo zpool)
jc_commands_describe=(
'acpi:run "acpi" command with magic syntax.'
'airport:run "airport" command with magic syntax.'
@@ -35,6 +35,7 @@ _jc() {
'git:run "git" command with magic syntax.'
'gpg:run "gpg" command with magic syntax.'
'hciconfig:run "hciconfig" command with magic syntax.'
+ 'host:run "host" command with magic syntax.'
'id:run "id" command with magic syntax.'
'ifconfig:run "ifconfig" command with magic syntax.'
'iostat:run "iostat" command with magic syntax.'
@@ -47,6 +48,7 @@ _jc() {
'lastb:run "lastb" command with magic syntax.'
'ls:run "ls" command with magic syntax.'
'lsattr:run "lsattr" command with magic syntax.'
+ 'lsb_release:run "lsb_release" command with magic syntax.'
'lsblk:run "lsblk" command with magic syntax.'
'lsmod:run "lsmod" command with magic syntax.'
'lsof:run "lsof" command with magic syntax.'
@@ -59,6 +61,7 @@ _jc() {
'mpstat:run "mpstat" command with magic syntax.'
'netstat:run "netstat" command with magic syntax.'
'nmcli:run "nmcli" command with magic syntax.'
+ 'nsd-control:run "nsd-control" command with magic syntax.'
'ntpq:run "ntpq" command with magic syntax.'
'os-prober:run "os-prober" command with magic syntax.'
'pidstat:run "pidstat" command with magic syntax.'
@@ -109,7 +112,7 @@ _jc() {
'zipinfo:run "zipinfo" command with magic syntax.'
'zpool:run "zpool" command with magic syntax.'
)
- jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --ntpq --openvpn --os-prober --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
+ jc_parsers=(--acpi --airport --airport-s --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --date --datetime-iso --df --dig --dir --dmidecode --dpkg-l --du --email-address --env --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --passwd --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --plist --postconf --proc --proc-buddyinfo --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_parsers_describe=(
'--acpi:`acpi` command parser'
'--airport:`airport -I` command parser'
@@ -157,6 +160,7 @@ _jc() {
'--hashsum:hashsum command parser (`md5sum`, `shasum`, etc.)'
'--hciconfig:`hciconfig` command parser'
'--history:`history` command parser'
+ '--host:`host` command parser'
'--hosts:`/etc/hosts` file parser'
'--id:`id` command parser'
'--ifconfig:`ifconfig` command parser'
@@ -177,6 +181,7 @@ _jc() {
'--ls:`ls` command parser'
'--ls-s:`ls` command streaming parser'
'--lsattr:`lsattr` command parser'
+ '--lsb-release:`lsb_release` command parser'
'--lsblk:`lsblk` command parser'
'--lsmod:`lsmod` command parser'
'--lsof:`lsof` command parser'
@@ -189,9 +194,11 @@ _jc() {
'--mpstat-s:`mpstat` command streaming parser'
'--netstat:`netstat` command parser'
'--nmcli:`nmcli` command parser'
+ '--nsd-control:`nsd-control` command parser'
'--ntpq:`ntpq -p` command parser'
'--openvpn:openvpn-status.log file parser'
'--os-prober:`os-prober` command parser'
+ '--os-release:`/etc/os-release` file parser'
'--passwd:`/etc/passwd` file parser'
'--pci-ids:`pci.ids` file parser'
'--pgpass:PostgreSQL password file parser'
diff --git a/docs/parsers/env.md b/docs/parsers/env.md
index 02f406b6..4aa19317 100644
--- a/docs/parsers/env.md
+++ b/docs/parsers/env.md
@@ -90,10 +90,10 @@ Parameters:
Returns:
- Dictionary of raw structured data or
- List of Dictionaries of processed structured data
+ Dictionary of raw structured data or (default)
+ List of Dictionaries of processed structured data (raw)
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
-Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/host.md b/docs/parsers/host.md
new file mode 100644
index 00000000..a4535d4c
--- /dev/null
+++ b/docs/parsers/host.md
@@ -0,0 +1,113 @@
+[Home](https://kellyjonbrazil.github.io/jc/)
+
+
+# jc.parsers.host
+
+jc - JSON Convert `host` command output parser
+
+Supports parsing of the most commonly used RR types (A, AAAA, MX, TXT)
+
+Usage (cli):
+
+ $ host google.com | jc --host
+
+or
+
+ $ jc host google.com
+
+Usage (module):
+
+ import jc
+ result = jc.parse('host', host_command_output)
+
+Schema:
+
+ [
+ {
+ "hostname": string,
+ "address": [
+ string
+ ],
+ "v6-address": [
+ string
+ ],
+ "mail": [
+ string
+ ]
+ }
+ ]
+
+ [
+ {
+ "nameserver": string,
+ "zone": string,
+ "mname": string,
+ "rname": string,
+ "serial": integer,
+ "refresh": integer,
+ "retry": integer,
+ "expire": integer,
+ "minimum": integer
+ }
+ ]
+
+Examples:
+
+ $ host google.com | jc --host
+ [
+ {
+ "hostname": "google.com",
+ "address": [
+ "142.251.39.110"
+ ],
+ "v6-address": [
+ "2a00:1450:400e:811::200e"
+ ],
+ "mail": [
+ "smtp.google.com."
+ ]
+ }
+ ]
+
+ $ jc host -C sunet.se
+ [
+ {
+ "nameserver": "2001:6b0:7::2",
+ "zone": "sunet.se",
+ "mname": "sunic.sunet.se.",
+ "rname": "hostmaster.sunet.se.",
+ "serial": "2023090401",
+ "refresh": "28800",
+ "retry": "7200",
+ "expire": "604800",
+ "minimum": "300"
+ },
+ {
+ ...
+ }
+ ]
+
+
+
+### parse
+
+```python
+def parse(data: str, raw: bool = False, quiet: bool = False)
+```
+
+Main text parsing function
+
+Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+Returns:
+
+ List of Dictionaries. Raw or processed structured data.
+
+### Parser Information
+Compatibility: linux, darwin, cygwin, win32, aix, freebsd
+
+Version 1.0 by Pettai (pettai@sunet.se)
diff --git a/docs/parsers/ini_dup.md b/docs/parsers/ini_dup.md
index e911969a..f53c4771 100644
--- a/docs/parsers/ini_dup.md
+++ b/docs/parsers/ini_dup.md
@@ -22,12 +22,12 @@ contained in lists/arrays.
Usage (cli):
- $ cat foo.ini | jc --ini
+ $ cat foo.ini | jc --ini-dup
Usage (module):
import jc
- result = jc.parse('ini', ini_file_output)
+ result = jc.parse('ini_dup', ini_file_output)
Schema:
@@ -67,7 +67,7 @@ Examples:
fruit = peach
color = green
- $ cat example.ini | jc --ini -p
+ $ cat example.ini | jc --ini-dup -p
{
"foo": [
"fiz"
@@ -118,4 +118,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
-Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/lsb_release.md b/docs/parsers/lsb_release.md
new file mode 100644
index 00000000..281298f6
--- /dev/null
+++ b/docs/parsers/lsb_release.md
@@ -0,0 +1,61 @@
+[Home](https://kellyjonbrazil.github.io/jc/)
+
+
+# jc.parsers.lsb\_release
+
+jc - JSON Convert `lsb_release` command parser
+
+This parser is an alias to the Key/Value parser (`--kv`).
+
+Usage (cli):
+
+ $ lsb_release -a | jc --lsb-release
+
+or
+ $ jc lsb_release -a
+
+Usage (module):
+
+ import jc
+ result = jc.parse('lsb_release', lsb_release_command_output)
+
+Schema:
+
+ {
+ "": string
+ }
+
+Examples:
+
+ $ lsb_release -a | jc --lsb-release -p
+ {
+ "Distributor ID": "Ubuntu",
+ "Description": "Ubuntu 16.04.6 LTS",
+ "Release": "16.04",
+ "Codename": "xenial"
+ }
+
+
+
+### parse
+
+```python
+def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
+```
+
+Main text parsing function
+
+Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+Returns:
+
+ Dictionary. Raw or processed structured data.
+
+### Parser Information
+Compatibility: linux, darwin, cygwin, win32, aix, freebsd
+
+Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/netstat.md b/docs/parsers/netstat.md
index 4c657ca1..9b184492 100644
--- a/docs/parsers/netstat.md
+++ b/docs/parsers/netstat.md
@@ -378,4 +378,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd, win32
-Version 1.14 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.15 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/nsd_control.md b/docs/parsers/nsd_control.md
new file mode 100644
index 00000000..23331505
--- /dev/null
+++ b/docs/parsers/nsd_control.md
@@ -0,0 +1,90 @@
+[Home](https://kellyjonbrazil.github.io/jc/)
+
+
+# jc.parsers.nsd\_control
+
+jc - JSON Convert `nsd-control` command output parser
+
+Usage (cli):
+
+ $ nsd-control | jc --nsd-control
+
+or
+
+ $ jc nsd-control
+
+Usage (module):
+
+ import jc
+ result = jc.parse('nsd_control', nsd_control_command_output)
+
+Schema:
+
+ [
+ {
+ "version": string,
+ "verbosity": integer,
+ "ratelimit": integer
+ }
+ ]
+
+ [
+ {
+ "zone": string
+ "status": {
+ "state": string,
+ "served-serial": string,
+ "commit-serial": string,
+ "wait": string
+ }
+ }
+ ]
+
+Examples:
+
+ $ nsd-control | jc --nsd-control status
+ [
+ {
+ "version": "4.6.2",
+ "verbosity": "2",
+ "ratelimit": "0"
+ }
+ ]
+
+ $ nsd-control | jc --nsd-control zonestatus sunet.se
+ [
+ {
+ "zone": "sunet.se",
+ "status": {
+ "state": "ok",
+ "served-serial": "2023090704 since 2023-09-07T16:34:27",
+ "commit-serial": "2023090704 since 2023-09-07T16:34:27",
+ "wait": "28684 sec between attempts"
+ }
+ }
+ ]
+
+
+
+### parse
+
+```python
+def parse(data: str, raw: bool = False, quiet: bool = False)
+```
+
+Main text parsing function
+
+Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+Returns:
+
+ List of Dictionaries. Raw or processed structured data.
+
+### Parser Information
+Compatibility: linux, darwin, cygwin, win32, aix, freebsd
+
+Version 1.0 by Pettai (pettai@sunet.se)
diff --git a/docs/parsers/os_release.md b/docs/parsers/os_release.md
new file mode 100644
index 00000000..9bd9fe83
--- /dev/null
+++ b/docs/parsers/os_release.md
@@ -0,0 +1,86 @@
+[Home](https://kellyjonbrazil.github.io/jc/)
+
+
+# jc.parsers.os\_release
+
+jc - JSON Convert `/etc/os-release` file parser
+
+This parser is an alias to the Key/Value parser (`--kv`).
+
+Usage (cli):
+
+ $ cat /etc/os-release | jc --os-release
+
+Usage (module):
+
+ import jc
+ result = jc.parse('os_release', os_release_output)
+
+Schema:
+
+ {
+ "": string
+ }
+
+Examples:
+
+ $ cat /etc/os-release | jc --os-release -p
+ {
+ "NAME": "CentOS Linux",
+ "VERSION": "7 (Core)",
+ "ID": "centos",
+ "ID_LIKE": "rhel fedora",
+ "VERSION_ID": "7",
+ "PRETTY_NAME": "CentOS Linux 7 (Core)",
+ "ANSI_COLOR": "0;31",
+ "CPE_NAME": "cpe:/o:centos:centos:7",
+ "HOME_URL": "https://www.centos.org/",
+ "BUG_REPORT_URL": "https://bugs.centos.org/",
+ "CENTOS_MANTISBT_PROJECT": "CentOS-7",
+ "CENTOS_MANTISBT_PROJECT_VERSION": "7",
+ "REDHAT_SUPPORT_PRODUCT": "centos",
+ "REDHAT_SUPPORT_PRODUCT_VERSION": "7"
+ }
+
+ $ cat /etc/os-release | jc --os-release -p -r
+ {
+ "NAME": "\\"CentOS Linux\\"",
+ "VERSION": "\\"7 (Core)\\"",
+ "ID": "\\"centos\\"",
+ "ID_LIKE": "\\"rhel fedora\\"",
+ "VERSION_ID": "\\"7\\"",
+ "PRETTY_NAME": "\\"CentOS Linux 7 (Core)\\"",
+ "ANSI_COLOR": "\\"0;31\\"",
+ "CPE_NAME": "\\"cpe:/o:centos:centos:7\\"",
+ "HOME_URL": "\\"https://www.centos.org/\\"",
+ "BUG_REPORT_URL": "\\"https://bugs.centos.org/\\"",
+ "CENTOS_MANTISBT_PROJECT": "\\"CentOS-7\\"",
+ "CENTOS_MANTISBT_PROJECT_VERSION": "\\"7\\"",
+ "REDHAT_SUPPORT_PRODUCT": "\\"centos\\"",
+ "REDHAT_SUPPORT_PRODUCT_VERSION": "\\"7\\""
+ }
+
+
+
+### parse
+
+```python
+def parse(data: str, raw: bool = False, quiet: bool = False) -> JSONDictType
+```
+
+Main text parsing function
+
+Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+Returns:
+
+ Dictionary. Raw or processed structured data.
+
+### Parser Information
+Compatibility: linux, darwin, cygwin, win32, aix, freebsd
+
+Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/pidstat.md b/docs/parsers/pidstat.md
index b40ad23c..526a42b7 100644
--- a/docs/parsers/pidstat.md
+++ b/docs/parsers/pidstat.md
@@ -45,6 +45,9 @@ Schema:
"kb_ccwr_s": float,
"cswch_s": float,
"nvcswch_s": float,
+ "usr_ms": integer,
+ "system_ms": integer,
+ "guest_ms": integer,
"command": string
}
]
@@ -148,4 +151,4 @@ Returns:
### Parser Information
Compatibility: linux
-Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/pidstat_s.md b/docs/parsers/pidstat_s.md
index f3639c16..61aa043d 100644
--- a/docs/parsers/pidstat_s.md
+++ b/docs/parsers/pidstat_s.md
@@ -39,6 +39,7 @@ Schema:
"percent_usr": float,
"percent_system": float,
"percent_guest": float,
+ "percent_wait": float,
"percent_cpu": float,
"cpu": integer,
"minflt_s": float,
@@ -53,6 +54,9 @@ Schema:
"kb_ccwr_s": float,
"cswch_s": float,
"nvcswch_s": float,
+ "usr_ms": integer,
+ "system_ms": integer,
+ "guest_ms": integer,
"command": string,
# below object only exists if using -qq or ignore_exceptions=True
@@ -107,4 +111,4 @@ Returns:
### Parser Information
Compatibility: linux
-Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/ping.md b/docs/parsers/ping.md
index 2f884b43..f8437285 100644
--- a/docs/parsers/ping.md
+++ b/docs/parsers/ping.md
@@ -35,6 +35,8 @@ Schema:
"packets_received": integer,
"packet_loss_percent": float,
"duplicates": integer,
+ "errors": integer,
+ "corrupted": integer,
"round_trip_ms_min": float,
"round_trip_ms_avg": float,
"round_trip_ms_max": float,
@@ -185,4 +187,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
-Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/ping_s.md b/docs/parsers/ping_s.md
index 07c4f165..d240cf5d 100644
--- a/docs/parsers/ping_s.md
+++ b/docs/parsers/ping_s.md
@@ -36,7 +36,7 @@ Schema:
"source_ip": string,
"destination_ip": string,
"sent_bytes": integer,
- "pattern": string, # (null if not set)
+ "pattern": string, # null if not set
"destination": string,
"timestamp": float,
"response_bytes": integer,
@@ -49,10 +49,12 @@ Schema:
"packets_received": integer,
"packet_loss_percent": float,
"duplicates": integer,
- "round_trip_ms_min": float,
- "round_trip_ms_avg": float,
- "round_trip_ms_max": float,
- "round_trip_ms_stddev": float,
+ "errors": integer, # null if not set
+ "corrupted": integer, # null if not set
+ "round_trip_ms_min": float, # null if not set
+ "round_trip_ms_avg": float, # null if not set
+ "round_trip_ms_max": float, # null if not set
+ "round_trip_ms_stddev": float, # null if not set
# below object only exists if using -qq or ignore_exceptions=True
"_jc_meta": {
@@ -106,4 +108,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, freebsd
-Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/ver.md b/docs/parsers/ver.md
index 8bdee50e..0759c2aa 100644
--- a/docs/parsers/ver.md
+++ b/docs/parsers/ver.md
@@ -7,7 +7,7 @@ jc - JSON Convert Version string output parser
Best-effort attempt to parse various styles of version numbers. This parser
is based off of the version parser included in the CPython distutils
-libary.
+library.
If the version string conforms to some de facto-standard versioning rules
followed by many developers a `strict` key will be present in the output
diff --git a/docs/parsers/x509_cert.md b/docs/parsers/x509_cert.md
index 7fe2a77f..4843d01d 100644
--- a/docs/parsers/x509_cert.md
+++ b/docs/parsers/x509_cert.md
@@ -433,4 +433,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
-Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/xml.md b/docs/parsers/xml.md
index eb838faf..e02d5e15 100644
--- a/docs/parsers/xml.md
+++ b/docs/parsers/xml.md
@@ -98,4 +98,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
-Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
+Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/xrandr.md b/docs/parsers/xrandr.md
index b3c355fc..63ebbeec 100644
--- a/docs/parsers/xrandr.md
+++ b/docs/parsers/xrandr.md
@@ -31,8 +31,8 @@ Schema:
"current_height": integer,
"maximum_width": integer,
"maximum_height": integer,
- "associated_device": {
- "associated_modes": [
+ "devices": {
+ "modes": [
{
"resolution_width": integer,
"resolution_height": integer,
@@ -63,24 +63,6 @@ Schema:
"reflection": string
}
],
- "unassociated_devices": [
- {
- "associated_modes": [
- {
- "resolution_width": integer,
- "resolution_height": integer,
- "is_high_resolution": boolean,
- "frequencies": [
- {
- "frequency": float,
- "is_current": boolean,
- "is_preferred": boolean
- }
- ]
- }
- ]
- }
- ]
}
Examples:
@@ -96,8 +78,8 @@ Examples:
"current_height": 1080,
"maximum_width": 32767,
"maximum_height": 32767,
- "associated_device": {
- "associated_modes": [
+ "devices": {
+ "modes": [
{
"resolution_width": 1920,
"resolution_height": 1080,
@@ -141,8 +123,7 @@ Examples:
"reflection": "normal"
}
}
- ],
- "unassociated_devices": []
+ ]
}
$ xrandr --properties | jc --xrandr -p
@@ -156,8 +137,8 @@ Examples:
"current_height": 1080,
"maximum_width": 32767,
"maximum_height": 32767,
- "associated_device": {
- "associated_modes": [
+ "devices": {
+ "modes": [
{
"resolution_width": 1920,
"resolution_height": 1080,
@@ -204,8 +185,7 @@ Examples:
"reflection": "normal"
}
}
- ],
- "unassociated_devices": []
+ ]
}
@@ -231,4 +211,4 @@ Returns:
### Parser Information
Compatibility: linux, darwin, cygwin, aix, freebsd
-Version 1.2 by Kevin Lyter (lyter_git at sent.com)
+Version 1.3 by Kevin Lyter (code (at) lyterk.com)
diff --git a/jc/cli.py b/jc/cli.py
index dd175b59..1fc2fa95 100644
--- a/jc/cli.py
+++ b/jc/cli.py
@@ -145,33 +145,34 @@ class JcCli():
JC_COLORS=blue,brightblack,magenta,green
JC_COLORS=default,default,default,default
"""
- input_error = False
- env_colors = os.getenv('JC_COLORS')
+ if PYGMENTS_INSTALLED:
+ input_error = False
+ env_colors = os.getenv('JC_COLORS')
- if env_colors:
- color_list = env_colors.split(',')
- else:
- color_list = ['default', 'default', 'default', 'default']
+ if env_colors:
+ color_list = env_colors.split(',')
+ else:
+ color_list = ['default', 'default', 'default', 'default']
- if len(color_list) != 4:
- input_error = True
-
- for color in color_list:
- if color != 'default' and color not in PYGMENT_COLOR:
+ if len(color_list) != 4:
input_error = True
- # if there is an issue with the env variable, just set all colors to default and move on
- if input_error:
- utils.warning_message(['Could not parse JC_COLORS environment variable'])
- color_list = ['default', 'default', 'default', 'default']
+ for color in color_list:
+ if color != 'default' and color not in PYGMENT_COLOR:
+ input_error = True
- # Try the color set in the JC_COLORS env variable first. If it is set to default, then fall back to default colors
- self.custom_colors = {
- Name.Tag: f'bold {PYGMENT_COLOR[color_list[0]]}' if color_list[0] != 'default' else f"bold {PYGMENT_COLOR['blue']}", # key names
- Keyword: PYGMENT_COLOR[color_list[1]] if color_list[1] != 'default' else PYGMENT_COLOR['brightblack'], # true, false, null
- Number: PYGMENT_COLOR[color_list[2]] if color_list[2] != 'default' else PYGMENT_COLOR['magenta'], # numbers
- String: PYGMENT_COLOR[color_list[3]] if color_list[3] != 'default' else PYGMENT_COLOR['green'] # strings
- }
+ # if there is an issue with the env variable, just set all colors to default and move on
+ if input_error:
+ utils.warning_message(['Could not parse JC_COLORS environment variable'])
+ color_list = ['default', 'default', 'default', 'default']
+
+ # Try the color set in the JC_COLORS env variable first. If it is set to default, then fall back to default colors
+ self.custom_colors = {
+ Name.Tag: f'bold {PYGMENT_COLOR[color_list[0]]}' if color_list[0] != 'default' else f"bold {PYGMENT_COLOR['blue']}", # key names
+ Keyword: PYGMENT_COLOR[color_list[1]] if color_list[1] != 'default' else PYGMENT_COLOR['brightblack'], # true, false, null
+ Number: PYGMENT_COLOR[color_list[2]] if color_list[2] != 'default' else PYGMENT_COLOR['magenta'], # numbers
+ String: PYGMENT_COLOR[color_list[3]] if color_list[3] != 'default' else PYGMENT_COLOR['green'] # strings
+ }
def set_mono(self) -> None:
"""
diff --git a/jc/lib.py b/jc/lib.py
index 36f02fda..acccd384 100644
--- a/jc/lib.py
+++ b/jc/lib.py
@@ -9,7 +9,7 @@ from .jc_types import ParserInfoType, JSONDictType
from jc import appdirs
-__version__ = '1.23.4'
+__version__ = '1.23.5'
parsers: List[str] = [
'acpi',
@@ -58,6 +58,7 @@ parsers: List[str] = [
'hashsum',
'hciconfig',
'history',
+ 'host',
'hosts',
'id',
'ifconfig',
@@ -79,6 +80,7 @@ parsers: List[str] = [
'ls',
'ls-s',
'lsattr',
+ 'lsb-release',
'lsblk',
'lsmod',
'lsof',
@@ -91,9 +93,11 @@ parsers: List[str] = [
'mpstat-s',
'netstat',
'nmcli',
+ 'nsd-control',
'ntpq',
'openvpn',
'os-prober',
+ 'os-release',
'passwd',
'pci-ids',
'pgpass',
diff --git a/jc/parsers/asn1crypto/core.py b/jc/parsers/asn1crypto/core.py
index 0908fd0d..2e7d5098 100644
--- a/jc/parsers/asn1crypto/core.py
+++ b/jc/parsers/asn1crypto/core.py
@@ -2333,8 +2333,8 @@ class BitString(_IntegerBitString, Constructable, Castable, Primitive, ValueMap)
if self._map:
self._native = set()
for index, bit in enumerate(bits):
- if bit:
- name = self._map.get(index, index)
+ if bit and index in self._map:
+ name = self._map.get(index)
self._native.add(name)
else:
self._native = bits
diff --git a/jc/parsers/crontab.py b/jc/parsers/crontab.py
index dc0a0168..3fae53b8 100644
--- a/jc/parsers/crontab.py
+++ b/jc/parsers/crontab.py
@@ -198,7 +198,7 @@ def _process(proc_data):
Dictionary. Structured data to conform to the schema.
"""
- # put itmes in lists
+ # put items in lists
try:
for entry in proc_data['schedule']:
entry['minute'] = entry['minute'].split(',')
diff --git a/jc/parsers/crontab_u.py b/jc/parsers/crontab_u.py
index 76fd1ac6..345a8e91 100644
--- a/jc/parsers/crontab_u.py
+++ b/jc/parsers/crontab_u.py
@@ -194,7 +194,7 @@ def _process(proc_data):
Dictionary. Structured data to conform to the schema.
"""
- # put itmes in lists
+ # put items in lists
try:
for entry in proc_data['schedule']:
entry['minute'] = entry['minute'].split(',')
diff --git a/jc/parsers/env.py b/jc/parsers/env.py
index 1d4bb68a..4f2280c8 100644
--- a/jc/parsers/env.py
+++ b/jc/parsers/env.py
@@ -67,12 +67,13 @@ Examples:
"_": "/usr/bin/env"
}
"""
+import re
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.4'
+ version = '1.5'
description = '`env` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -83,6 +84,7 @@ class info():
__version__ = info.version
+VAR_DEF_PATTERN = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*=\S*.*$')
def _process(proc_data):
"""
@@ -96,8 +98,6 @@ def _process(proc_data):
List of Dictionaries. Structured data to conform to the schema.
"""
-
- # rebuild output for added semantic information
processed = []
for k, v in proc_data.items():
proc_line = {}
@@ -120,24 +120,29 @@ def parse(data, raw=False, quiet=False):
Returns:
- Dictionary of raw structured data or
- List of Dictionaries of processed structured data
+ Dictionary of raw structured data or (default)
+ List of Dictionaries of processed structured data (raw)
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output = {}
-
- # Clear any blank lines
- cleandata = list(filter(None, data.splitlines()))
+ key = ''
+ value = None
if jc.utils.has_data(data):
+ for line in data.splitlines():
+ if VAR_DEF_PATTERN.match(line):
+ if not value is None:
+ raw_output[key] = value
+ key, value = line.split('=', maxsplit=1)
+ continue
- for entry in cleandata:
- parsed_line = entry.split('=', maxsplit=1)
- raw_output[parsed_line[0]] = parsed_line[1]
+ if not value is None:
+ value = value + '\n' + line
+
+ if not value is None:
+ raw_output[key] = value
+
+ return raw_output if raw else _process(raw_output)
- if raw:
- return raw_output
- else:
- return _process(raw_output)
diff --git a/jc/parsers/host.py b/jc/parsers/host.py
new file mode 100644
index 00000000..a026a0b5
--- /dev/null
+++ b/jc/parsers/host.py
@@ -0,0 +1,243 @@
+"""jc - JSON Convert `host` command output parser
+
+Supports parsing of the most commonly used RR types (A, AAAA, MX, TXT)
+
+Usage (cli):
+
+ $ host google.com | jc --host
+
+or
+
+ $ jc host google.com
+
+Usage (module):
+
+ import jc
+ result = jc.parse('host', host_command_output)
+
+Schema:
+
+ [
+ {
+ "hostname": string,
+ "address": [
+ string
+ ],
+ "v6-address": [
+ string
+ ],
+ "mail": [
+ string
+ ]
+ }
+ ]
+
+ [
+ {
+ "nameserver": string,
+ "zone": string,
+ "mname": string,
+ "rname": string,
+ "serial": integer,
+ "refresh": integer,
+ "retry": integer,
+ "expire": integer,
+ "minimum": integer
+ }
+ ]
+
+Examples:
+
+ $ host google.com | jc --host
+ [
+ {
+ "hostname": "google.com",
+ "address": [
+ "142.251.39.110"
+ ],
+ "v6-address": [
+ "2a00:1450:400e:811::200e"
+ ],
+ "mail": [
+ "smtp.google.com."
+ ]
+ }
+ ]
+
+ $ jc host -C sunet.se
+ [
+ {
+ "nameserver": "2001:6b0:7::2",
+ "zone": "sunet.se",
+ "mname": "sunic.sunet.se.",
+ "rname": "hostmaster.sunet.se.",
+ "serial": "2023090401",
+ "refresh": "28800",
+ "retry": "7200",
+ "expire": "604800",
+ "minimum": "300"
+ },
+ {
+ ...
+ }
+ ]
+"""
+from typing import Dict, List
+import jc.utils
+
+
+class info():
+ """Provides parser metadata (version, author, etc.)"""
+ version = '1.0'
+ description = '`host` command parser'
+ author = 'Pettai'
+ author_email = 'pettai@sunet.se'
+ compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
+ tags = ['command']
+ magic_commands = ['host']
+
+
+__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.
+ """
+
+ int_list = {'serial', 'refresh', 'retry', 'expire', 'minimum'}
+
+ for entry in proc_data:
+ for key in entry:
+ if key in int_list:
+ entry[key] = jc.utils.convert_to_int(entry[key])
+
+ return proc_data
+
+
+def parse(data: str, raw: bool = False, quiet: bool = False):
+ """
+ Main text parsing function
+
+ Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+ Returns:
+
+ List of Dictionaries. Raw or processed structured data.
+ """
+ jc.utils.compatibility(__name__, info.compatible, quiet)
+ jc.utils.input_type_check(data)
+
+ raw_output: List[Dict] = []
+
+ warned = False
+
+ if jc.utils.has_data(data):
+
+ addresses = []
+ v6addresses = []
+ mail = []
+ text = []
+ rrdata = {}
+ soaparse = False
+
+ for line in filter(None, data.splitlines()):
+ line = line.strip()
+
+ # default
+ if ' has address ' in line:
+ linedata = line.split(' ', maxsplit=3)
+ hostname = linedata[0]
+ address = linedata[3]
+ addresses.append(address)
+ rrdata.update({'hostname': hostname})
+ rrdata.update({'address': addresses})
+ continue
+
+ if ' has IPv6 address ' in line:
+ linedata = line.split(' ', maxsplit=4)
+ hostname = linedata[0]
+ v6address = linedata[4]
+ v6addresses.append(v6address)
+ rrdata.update({'hostname': hostname})
+ rrdata.update({'v6-address': v6addresses})
+ continue
+
+ if ' mail is handled by ' in line:
+ linedata = line.split(' ', maxsplit=6)
+ hostname = linedata[0]
+ mx = linedata[6]
+ mail.append(mx)
+ rrdata.update({'hostname': hostname})
+ rrdata.update({'mail': mail})
+ continue
+
+
+ # TXT parsing
+ if ' descriptive text ' in line:
+ linedata = line.split('descriptive text "', maxsplit=1)
+ hostname = linedata[0]
+ txt = linedata[1].strip('"')
+ text.append(txt)
+ rrdata.update({'hostname': hostname})
+ rrdata.update({'text': text})
+ continue
+
+
+ # -C / SOA parsing
+ if line.startswith('Nameserver '):
+ soaparse = True
+ rrdata = {}
+ linedata = line.split(' ', maxsplit=1)
+ nameserverip = linedata[1].rstrip(':')
+ rrdata.update({'nameserver': nameserverip})
+ continue
+
+ if ' has SOA record ' in line:
+ linedata = line.split(' ', maxsplit=10)
+
+ zone = linedata[0]
+ mname = linedata[4]
+ rname = linedata[5]
+ serial = linedata[6]
+ refresh = linedata[7]
+ retry = linedata[8]
+ expire = linedata[9]
+ minimum = linedata[10]
+
+ try:
+ rrdata.update(
+ {
+ 'zone': zone,
+ 'mname': mname,
+ 'rname': rname,
+ 'serial': serial,
+ 'refresh': refresh,
+ 'retry': retry,
+ 'expire': expire,
+ 'minimum': minimum
+ },
+ )
+ raw_output.append(rrdata)
+
+ except IndexError:
+ if not warned:
+ jc.utils.warning_message(['Unknown format detected.'])
+ warned = True
+
+ if not soaparse:
+ raw_output.append(rrdata)
+
+ return raw_output if raw else _process(raw_output)
diff --git a/jc/parsers/ini_dup.py b/jc/parsers/ini_dup.py
index ae1661c0..48408dbe 100644
--- a/jc/parsers/ini_dup.py
+++ b/jc/parsers/ini_dup.py
@@ -17,12 +17,12 @@ contained in lists/arrays.
Usage (cli):
- $ cat foo.ini | jc --ini
+ $ cat foo.ini | jc --ini-dup
Usage (module):
import jc
- result = jc.parse('ini', ini_file_output)
+ result = jc.parse('ini_dup', ini_file_output)
Schema:
@@ -62,7 +62,7 @@ Examples:
fruit = peach
color = green
- $ cat example.ini | jc --ini -p
+ $ cat example.ini | jc --ini-dup -p
{
"foo": [
"fiz"
@@ -97,7 +97,7 @@ import uuid
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.0'
+ version = '1.1'
description = 'INI with duplicate key file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
diff --git a/jc/parsers/lsb_release.py b/jc/parsers/lsb_release.py
new file mode 100644
index 00000000..aa3c8dd1
--- /dev/null
+++ b/jc/parsers/lsb_release.py
@@ -0,0 +1,89 @@
+"""jc - JSON Convert `lsb_release` command parser
+
+This parser is an alias to the Key/Value parser (`--kv`).
+
+Usage (cli):
+
+ $ lsb_release -a | jc --lsb-release
+
+or
+ $ jc lsb_release -a
+
+Usage (module):
+
+ import jc
+ result = jc.parse('lsb_release', lsb_release_command_output)
+
+Schema:
+
+ {
+ "": string
+ }
+
+Examples:
+
+ $ lsb_release -a | jc --lsb-release -p
+ {
+ "Distributor ID": "Ubuntu",
+ "Description": "Ubuntu 16.04.6 LTS",
+ "Release": "16.04",
+ "Codename": "xenial"
+ }
+"""
+from jc.jc_types import JSONDictType
+import jc.parsers.kv
+import jc.utils
+
+
+class info():
+ """Provides parser metadata (version, author, etc.)"""
+ version = '1.0'
+ description = '`lsb_release` command parser'
+ author = 'Kelly Brazil'
+ author_email = 'kellyjonbrazil@gmail.com'
+ details = 'Using the Key/Value parser'
+ compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
+ magic_commands = ['lsb_release']
+ tags = ['command']
+
+
+__version__ = info.version
+
+
+def _process(proc_data: JSONDictType) -> JSONDictType:
+ """
+ Final processing to conform to the schema.
+
+ Parameters:
+
+ proc_data: (Dictionary) raw structured data to process
+
+ Returns:
+
+ Dictionary. Structured to conform to the schema.
+ """
+ return jc.parsers.kv._process(proc_data)
+
+
+def parse(
+ data: str,
+ raw: bool = False,
+ quiet: bool = False
+) -> JSONDictType:
+ """
+ Main text parsing function
+
+ Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+ Returns:
+
+ Dictionary. Raw or processed structured data.
+ """
+ jc.utils.compatibility(__name__, info.compatible, quiet)
+ raw_output = jc.parsers.kv.parse(data, raw, quiet)
+
+ return raw_output if raw else _process(raw_output)
diff --git a/jc/parsers/mount.py b/jc/parsers/mount.py
index 301e35e4..ef8a49dc 100644
--- a/jc/parsers/mount.py
+++ b/jc/parsers/mount.py
@@ -160,7 +160,7 @@ def _aix_parse(data):
# AIX mount entries have the remote node as the zeroth element. If the
# mount is local, the zeroth element is the filesystem instead. We can
- # detect this by the lenth of the list. For local mounts, length is 7,
+ # detect this by the length of the list. For local mounts, length is 7,
# and for remote mounts, the length is 8. In the remote case, pop off
# the zeroth element. Then parsed_line has a consistent format.
if len(parsed_line) == 8:
diff --git a/jc/parsers/netstat.py b/jc/parsers/netstat.py
index 2842c796..df715541 100644
--- a/jc/parsers/netstat.py
+++ b/jc/parsers/netstat.py
@@ -355,7 +355,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.14'
+ version = '1.15'
description = '`netstat` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
diff --git a/jc/parsers/netstat_linux.py b/jc/parsers/netstat_linux.py
index c43a61af..322fcab8 100644
--- a/jc/parsers/netstat_linux.py
+++ b/jc/parsers/netstat_linux.py
@@ -31,10 +31,19 @@ def normalize_interface_headers(header):
def parse_network(headers, entry):
+ LIST_OF_STATES = [
+ "ESTABLISHED", "SYN_SENT", "SYN_RECV", "FIN_WAIT1", "FIN_WAIT2",
+ "TIME_WAIT", "CLOSED", "CLOSE_WAIT", "LAST_ACK", "LISTEN", "CLOSING",
+ "UNKNOWN", "7"
+ ]
+
+ # split entry based on presence of value in "State" column
+ contains_state = any(state in entry for state in LIST_OF_STATES)
+ split_modifier = 1 if contains_state else 2
+ entry = entry.split(maxsplit=len(headers) - split_modifier)
+
# Count words in header
# if len of line is one less than len of header, then insert None in field 5
- entry = entry.split(maxsplit=len(headers) - 1)
-
if len(entry) == len(headers) - 1:
entry.insert(5, None)
diff --git a/jc/parsers/nsd_control.py b/jc/parsers/nsd_control.py
new file mode 100644
index 00000000..4faca968
--- /dev/null
+++ b/jc/parsers/nsd_control.py
@@ -0,0 +1,236 @@
+"""jc - JSON Convert `nsd-control` command output parser
+
+Usage (cli):
+
+ $ nsd-control | jc --nsd-control
+
+or
+
+ $ jc nsd-control
+
+Usage (module):
+
+ import jc
+ result = jc.parse('nsd_control', nsd_control_command_output)
+
+Schema:
+
+ [
+ {
+ "version": string,
+ "verbosity": integer,
+ "ratelimit": integer
+ }
+ ]
+
+ [
+ {
+ "zone": string
+ "status": {
+ "state": string,
+ "served-serial": string,
+ "commit-serial": string,
+ "wait": string
+ }
+ }
+ ]
+
+Examples:
+
+ $ nsd-control | jc --nsd-control status
+ [
+ {
+ "version": "4.6.2",
+ "verbosity": "2",
+ "ratelimit": "0"
+ }
+ ]
+
+ $ nsd-control | jc --nsd-control zonestatus sunet.se
+ [
+ {
+ "zone": "sunet.se",
+ "status": {
+ "state": "ok",
+ "served-serial": "2023090704 since 2023-09-07T16:34:27",
+ "commit-serial": "2023090704 since 2023-09-07T16:34:27",
+ "wait": "28684 sec between attempts"
+ }
+ }
+ ]
+
+"""
+from typing import List, Dict
+import jc.utils
+
+
+class info():
+ """Provides parser metadata (version, author, etc.)"""
+ version = '1.0'
+ description = '`nsd-control` command parser'
+ author = 'Pettai'
+ author_email = 'pettai@sunet.se'
+ compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
+ tags = ['command']
+ magic_commands = ['nsd-control']
+
+
+__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.
+ """
+ int_list = {'verbosity', 'ratelimit', 'wait'}
+
+ for entry in proc_data:
+ for key in entry:
+ if key in int_list:
+ entry[key] = jc.utils.convert_to_int(entry[key])
+
+ return proc_data
+
+
+def parse(data: str, raw: bool = False, quiet: bool = False):
+ """
+ Main text parsing function
+
+ Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+ Returns:
+
+ List of Dictionaries. Raw or processed structured data.
+ """
+ jc.utils.compatibility(__name__, info.compatible, quiet)
+ jc.utils.input_type_check(data)
+
+ raw_output: List[Dict] = []
+
+ if jc.utils.has_data(data):
+
+ itrparse = False
+ itr: Dict = {}
+
+ for line in filter(None, data.splitlines()):
+ line = line.strip()
+
+ # default 'ok'
+ if line.startswith('ok'):
+ raw_output.append({'command': 'ok'})
+ continue
+
+ # status
+ if line.startswith('version:'):
+ status = {}
+ linedata = line.split(':', maxsplit=1)
+ version = linedata[1].strip()
+ status.update({'version': version})
+ continue
+
+ if line.startswith('verbosity:'):
+ linedata = line.split(':', maxsplit=1)
+ verbosity = linedata[1]
+ status.update({'verbosity': verbosity})
+ continue
+
+ if line.startswith('ratelimit:'):
+ linedata = line.split(':', maxsplit=1)
+ ratelimit = linedata[1]
+ status.update({'ratelimit': ratelimit})
+ raw_output.append(status)
+ continue
+
+ # print_cookie_secrets
+ if line.startswith('active'):
+ itrparse = True
+ itr = {}
+ linedata = line.split(':', maxsplit=1)
+ active = linedata[1].strip()
+ itr.update({'active': active})
+ continue
+
+ if line.startswith('staging'):
+ linedata = line.split(':', maxsplit=1)
+ staging = linedata[1].strip()
+ itr.update({'staging': staging})
+ continue
+
+ # print_tsig
+ if line.startswith('key:'):
+ tsigs = {}
+ tsigdata = dict()
+ linedata = line.split(' ', maxsplit=6)
+ name = linedata[2].strip('"').rstrip('"')
+ tsigdata.update({'name': name})
+ secret = linedata[4].strip('"').rstrip('"')
+ tsigdata.update({'secret': secret})
+ algorithm = linedata[6].strip('"').rstrip('"')
+ tsigdata.update({'algorithm': algorithm})
+ tsigs.update({'key': tsigdata})
+ raw_output.append(tsigs)
+ continue
+
+ # zonestatus
+ if line.startswith('zone:'):
+ zonename: Dict = dict()
+ zstatus: Dict = dict()
+ linedata = line.split(':\t', maxsplit=1)
+ zone = linedata[1]
+ zonename.update({'zone': zone})
+ continue
+
+ if line.startswith('state:'):
+ linedata = line.split(': ', maxsplit=1)
+ state = linedata[1]
+ zstatus.update({'state': state})
+ continue
+
+ if line.startswith('served-serial:'):
+ linedata = line.split(': ', maxsplit=1)
+ served = linedata[1].strip('"').rstrip('"')
+ zstatus.update({'served-serial': served})
+ continue
+
+ if line.startswith('commit-serial:'):
+ linedata = line.split(': ', maxsplit=1)
+ commit = linedata[1].strip('"').rstrip('"')
+ zstatus.update({'commit-serial': commit})
+ continue
+
+ if line.startswith('wait:'):
+ linedata = line.split(': ', maxsplit=1)
+ wait = linedata[1].strip('"').rstrip('"')
+ zstatus.update({'wait': wait})
+ zonename.update({'status': zstatus})
+ raw_output.append(zonename)
+ continue
+
+ # stats
+ if line.startswith('server') or line.startswith('num.') or line.startswith('size.') or line.startswith('time.') or line.startswith('zone.'):
+ itrparse = True
+ linedata = line.split('=', maxsplit=1)
+ key = linedata[0]
+ if key.startswith('time.'):
+ value = float(linedata[1])
+ else:
+ value = int(linedata[1])
+ itr.update({key: value})
+ continue
+
+ if itrparse:
+ raw_output.append(itr)
+
+ return raw_output if raw else _process(raw_output)
diff --git a/jc/parsers/os_release.py b/jc/parsers/os_release.py
new file mode 100644
index 00000000..be11de59
--- /dev/null
+++ b/jc/parsers/os_release.py
@@ -0,0 +1,113 @@
+"""jc - JSON Convert `/etc/os-release` file parser
+
+This parser is an alias to the Key/Value parser (`--kv`).
+
+Usage (cli):
+
+ $ cat /etc/os-release | jc --os-release
+
+Usage (module):
+
+ import jc
+ result = jc.parse('os_release', os_release_output)
+
+Schema:
+
+ {
+ "": string
+ }
+
+Examples:
+
+ $ cat /etc/os-release | jc --os-release -p
+ {
+ "NAME": "CentOS Linux",
+ "VERSION": "7 (Core)",
+ "ID": "centos",
+ "ID_LIKE": "rhel fedora",
+ "VERSION_ID": "7",
+ "PRETTY_NAME": "CentOS Linux 7 (Core)",
+ "ANSI_COLOR": "0;31",
+ "CPE_NAME": "cpe:/o:centos:centos:7",
+ "HOME_URL": "https://www.centos.org/",
+ "BUG_REPORT_URL": "https://bugs.centos.org/",
+ "CENTOS_MANTISBT_PROJECT": "CentOS-7",
+ "CENTOS_MANTISBT_PROJECT_VERSION": "7",
+ "REDHAT_SUPPORT_PRODUCT": "centos",
+ "REDHAT_SUPPORT_PRODUCT_VERSION": "7"
+ }
+
+ $ cat /etc/os-release | jc --os-release -p -r
+ {
+ "NAME": "\\"CentOS Linux\\"",
+ "VERSION": "\\"7 (Core)\\"",
+ "ID": "\\"centos\\"",
+ "ID_LIKE": "\\"rhel fedora\\"",
+ "VERSION_ID": "\\"7\\"",
+ "PRETTY_NAME": "\\"CentOS Linux 7 (Core)\\"",
+ "ANSI_COLOR": "\\"0;31\\"",
+ "CPE_NAME": "\\"cpe:/o:centos:centos:7\\"",
+ "HOME_URL": "\\"https://www.centos.org/\\"",
+ "BUG_REPORT_URL": "\\"https://bugs.centos.org/\\"",
+ "CENTOS_MANTISBT_PROJECT": "\\"CentOS-7\\"",
+ "CENTOS_MANTISBT_PROJECT_VERSION": "\\"7\\"",
+ "REDHAT_SUPPORT_PRODUCT": "\\"centos\\"",
+ "REDHAT_SUPPORT_PRODUCT_VERSION": "\\"7\\""
+ }
+"""
+from jc.jc_types import JSONDictType
+import jc.parsers.kv
+import jc.utils
+
+
+class info():
+ """Provides parser metadata (version, author, etc.)"""
+ version = '1.0'
+ description = '`/etc/os-release` file parser'
+ author = 'Kelly Brazil'
+ author_email = 'kellyjonbrazil@gmail.com'
+ details = 'Using the Key/Value parser'
+ compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
+ tags = ['file', 'standard', 'string']
+
+
+__version__ = info.version
+
+
+def _process(proc_data: JSONDictType) -> JSONDictType:
+ """
+ Final processing to conform to the schema.
+
+ Parameters:
+
+ proc_data: (Dictionary) raw structured data to process
+
+ Returns:
+
+ Dictionary. Structured to conform to the schema.
+ """
+ return jc.parsers.kv._process(proc_data)
+
+
+def parse(
+ data: str,
+ raw: bool = False,
+ quiet: bool = False
+) -> JSONDictType:
+ """
+ Main text parsing function
+
+ Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+ Returns:
+
+ Dictionary. Raw or processed structured data.
+ """
+ jc.utils.compatibility(__name__, info.compatible, quiet)
+ raw_output = jc.parsers.kv.parse(data, raw, quiet)
+
+ return raw_output if raw else _process(raw_output)
diff --git a/jc/parsers/pidstat.py b/jc/parsers/pidstat.py
index c6271dda..29ac3aea 100644
--- a/jc/parsers/pidstat.py
+++ b/jc/parsers/pidstat.py
@@ -40,6 +40,9 @@ Schema:
"kb_ccwr_s": float,
"cswch_s": float,
"nvcswch_s": float,
+ "usr_ms": integer,
+ "system_ms": integer,
+ "guest_ms": integer,
"command": string
}
]
@@ -128,7 +131,7 @@ from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.1'
+ version = '1.3'
description = '`pidstat -H` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -152,11 +155,16 @@ def _process(proc_data: List[Dict]) -> List[Dict]:
List of Dictionaries. Structured to conform to the schema.
"""
- int_list = {'time', 'uid', 'pid', 'cpu', 'vsz', 'rss', 'stksize', 'stkref'}
+ int_list = {
+ 'time', 'uid', 'pid', 'cpu', 'vsz', 'rss', 'stksize', 'stkref',
+ 'usr_ms', 'system_ms', 'guest_ms'
+ }
- float_list = {'percent_usr', 'percent_system', 'percent_guest', 'percent_cpu',
- 'minflt_s', 'majflt_s', 'percent_mem', 'kb_rd_s', 'kb_wr_s',
- 'kb_ccwr_s', 'cswch_s', 'nvcswch_s'}
+ float_list = {
+ 'percent_usr', 'percent_system', 'percent_guest', 'percent_cpu',
+ 'minflt_s', 'majflt_s', 'percent_mem', 'kb_rd_s', 'kb_wr_s',
+ 'kb_ccwr_s', 'cswch_s', 'nvcswch_s', 'percent_wait'
+ }
for entry in proc_data:
for key in entry:
@@ -169,6 +177,14 @@ def _process(proc_data: List[Dict]) -> List[Dict]:
return proc_data
+def normalize_header(header: str) -> str:
+ return header.replace('#', ' ')\
+ .replace('-', '_')\
+ .replace('/', '_')\
+ .replace('%', 'percent_')\
+ .lower()
+
+
def parse(
data: str,
raw: bool = False,
@@ -191,29 +207,28 @@ def parse(
jc.utils.input_type_check(data)
raw_output: List = []
+ table_list: List = []
+ header_found = False
if jc.utils.has_data(data):
- # check for line starting with # as the start of the table
data_list = list(filter(None, data.splitlines()))
- for line in data_list.copy():
- if line.startswith('#'):
- break
- else:
- data_list.pop(0)
- if not data_list:
+ for line in data_list:
+ if line.startswith('#'):
+ header_found = True
+ if len(table_list) > 1:
+ raw_output.extend(simple_table_parse(table_list))
+ table_list = [normalize_header(line)]
+ continue
+
+ if header_found:
+ table_list.append(line)
+
+ if len(table_list) > 1:
+ raw_output.extend(simple_table_parse(table_list))
+
+ if not header_found:
raise ParseError('Could not parse pidstat output. Make sure to use "pidstat -h".')
- # normalize header
- data_list[0] = data_list[0].replace('#', ' ')\
- .replace('/', '_')\
- .replace('%', 'percent_')\
- .lower()
-
- # remove remaining header lines (e.g. pidstat -H 2 5)
- data_list = [i for i in data_list if not i.startswith('#')]
-
- raw_output = simple_table_parse(data_list)
-
return raw_output if raw else _process(raw_output)
diff --git a/jc/parsers/pidstat_s.py b/jc/parsers/pidstat_s.py
index dbaee0d6..c347a13a 100644
--- a/jc/parsers/pidstat_s.py
+++ b/jc/parsers/pidstat_s.py
@@ -34,6 +34,7 @@ Schema:
"percent_usr": float,
"percent_system": float,
"percent_guest": float,
+ "percent_wait": float,
"percent_cpu": float,
"cpu": integer,
"minflt_s": float,
@@ -48,6 +49,9 @@ Schema:
"kb_ccwr_s": float,
"cswch_s": float,
"nvcswch_s": float,
+ "usr_ms": integer,
+ "system_ms": integer,
+ "guest_ms": integer,
"command": string,
# below object only exists if using -qq or ignore_exceptions=True
@@ -72,7 +76,7 @@ Examples:
{"time":"1646859134","uid":"0","pid":"9","percent_usr":"0.00","perc...}
...
"""
-from typing import Dict, Iterable, Union
+from typing import List, Dict, Iterable, Union
import jc.utils
from jc.streaming import (
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
@@ -83,7 +87,7 @@ from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.1'
+ version = '1.2'
description = '`pidstat -H` command streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -107,11 +111,16 @@ def _process(proc_data: Dict) -> Dict:
Dictionary. Structured data to conform to the schema.
"""
- int_list = {'time', 'uid', 'pid', 'cpu', 'vsz', 'rss', 'stksize', 'stkref'}
+ int_list = {
+ 'time', 'uid', 'pid', 'cpu', 'vsz', 'rss', 'stksize', 'stkref',
+ 'usr_ms', 'system_ms', 'guest_ms'
+ }
- float_list = {'percent_usr', 'percent_system', 'percent_guest', 'percent_cpu',
- 'minflt_s', 'majflt_s', 'percent_mem', 'kb_rd_s', 'kb_wr_s',
- 'kb_ccwr_s', 'cswch_s', 'nvcswch_s'}
+ float_list = {
+ 'percent_usr', 'percent_system', 'percent_guest', 'percent_wait',
+ 'percent_cpu', 'minflt_s', 'majflt_s', 'percent_mem', 'kb_rd_s',
+ 'kb_wr_s', 'kb_ccwr_s', 'cswch_s', 'nvcswch_s'
+ }
for key in proc_data:
if key in int_list:
@@ -123,6 +132,14 @@ def _process(proc_data: Dict) -> Dict:
return proc_data
+def normalize_header(header: str) -> str:
+ return header.replace('#', ' ')\
+ .replace('-', '_')\
+ .replace('/', '_')\
+ .replace('%', 'percent_')\
+ .lower()
+
+
@add_jc_meta
def parse(
data: Iterable[str],
@@ -149,8 +166,8 @@ def parse(
jc.utils.compatibility(__name__, info.compatible, quiet)
streaming_input_type_check(data)
- found_first_hash = False
- header = ''
+ table_list: List = []
+ header: str = ''
for line in data:
try:
@@ -161,29 +178,30 @@ def parse(
# skip blank lines
continue
- if not line.startswith('#') and not found_first_hash:
- # skip preamble lines before header row
+ if line.startswith('#'):
+ if len(table_list) > 1:
+ output_line = simple_table_parse(table_list)[0]
+ yield output_line if raw else _process(output_line)
+ header = ''
+
+ header = normalize_header(line)
+ table_list = [header]
continue
- if line.startswith('#') and not found_first_hash:
- # normalize header
- header = line.replace('#', ' ')\
- .replace('/', '_')\
- .replace('%', 'percent_')\
- .lower()
- found_first_hash = True
- continue
-
- if line.startswith('#') and found_first_hash:
- # skip header lines after first one is found
- continue
-
- output_line = simple_table_parse([header, line])[0]
-
- if output_line:
+ if header:
+ table_list.append(line)
+ output_line = simple_table_parse(table_list)[0]
yield output_line if raw else _process(output_line)
- else:
- raise ParseError('Not pidstat data')
+ table_list = [header]
+ continue
except Exception as e:
yield raise_or_yield(ignore_exceptions, e, line)
+
+ try:
+ if len(table_list) > 1:
+ output_line = simple_table_parse(table_list)[0]
+ yield output_line if raw else _process(output_line)
+
+ except Exception as e:
+ yield raise_or_yield(ignore_exceptions, e, str(table_list))
diff --git a/jc/parsers/ping.py b/jc/parsers/ping.py
index 18b83ecc..3d623445 100644
--- a/jc/parsers/ping.py
+++ b/jc/parsers/ping.py
@@ -30,6 +30,8 @@ Schema:
"packets_received": integer,
"packet_loss_percent": float,
"duplicates": integer,
+ "errors": integer,
+ "corrupted": integer,
"round_trip_ms_min": float,
"round_trip_ms_avg": float,
"round_trip_ms_max": float,
@@ -157,6 +159,7 @@ Examples:
]
}
"""
+import re
import string
import ipaddress
import jc.utils
@@ -164,7 +167,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.9'
+ version = '1.10'
description = '`ping` and `ping6` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -190,7 +193,7 @@ def _process(proc_data):
"""
int_list = {
'data_bytes', 'packets_transmitted', 'packets_received', 'bytes', 'icmp_seq', 'ttl',
- 'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'
+ 'duplicates', 'corrupted', 'errors', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'
}
float_list = {
@@ -321,41 +324,47 @@ def _linux_parse(data):
continue
if footer:
- if 'packets transmitted' in line:
- if ' duplicates,' in line:
- raw_output.update(
- {
- 'packets_transmitted': line.split()[0],
- 'packets_received': line.split()[3],
- 'packet_loss_percent': line.split()[7].rstrip('%'),
- 'duplicates': line.split()[5].lstrip('+'),
- 'time_ms': line.split()[11].replace('ms', '')
- }
- )
- continue
- else:
- raw_output.update(
- {
- 'packets_transmitted': line.split()[0],
- 'packets_received': line.split()[3],
- 'packet_loss_percent': line.split()[5].rstrip('%'),
- 'duplicates': '0',
- 'time_ms': line.split()[9].replace('ms', '')
- }
- )
- continue
+ # Init in zero, to keep compatibility with previous behaviour
+ if 'duplicates' not in raw_output:
+ raw_output['duplicates'] = '0'
- else:
- split_line = line.split(' = ')[1]
- split_line = split_line.split('/')
- raw_output.update(
- {
- 'round_trip_ms_min': split_line[0],
- 'round_trip_ms_avg': split_line[1],
- 'round_trip_ms_max': split_line[2],
- 'round_trip_ms_stddev': split_line[3].split()[0]
- }
- )
+ #
+ # See: https://github.com/dgibson/iputils/blob/master/ping_common.c#L995
+ #
+ m = re.search(r'(\d+) packets transmitted', line)
+ if m:
+ raw_output['packets_transmitted'] = m.group(1)
+
+ m = re.search(r'(\d+) received,', line)
+ if m:
+ raw_output['packets_received'] = m.group(1)
+
+ m = re.search(r'[+](\d+) duplicates', line)
+ if m:
+ raw_output['duplicates'] = m.group(1)
+
+ m = re.search(r'[+](\d+) corrupted', line)
+ if m:
+ raw_output['corrupted'] = m.group(1)
+
+ m = re.search(r'[+](\d+) errors', line)
+ if m:
+ raw_output['errors'] = m.group(1)
+
+ m = re.search(r'([\d\.]+)% packet loss', line)
+ if m:
+ raw_output['packet_loss_percent'] = m.group(1)
+
+ m = re.search(r'time (\d+)ms', line)
+ if m:
+ raw_output['time_ms'] = m.group(1)
+
+ m = re.search(r'rtt min\/avg\/max\/mdev += +([\d\.]+)\/([\d\.]+)\/([\d\.]+)\/([\d\.]+) ms', line)
+ if m:
+ raw_output['round_trip_ms_min'] = m.group(1)
+ raw_output['round_trip_ms_avg'] = m.group(2)
+ raw_output['round_trip_ms_max'] = m.group(3)
+ raw_output['round_trip_ms_stddev'] = m.group(4)
# ping response lines
else:
diff --git a/jc/parsers/ping_s.py b/jc/parsers/ping_s.py
index 1e141fe7..639fa83a 100644
--- a/jc/parsers/ping_s.py
+++ b/jc/parsers/ping_s.py
@@ -31,7 +31,7 @@ Schema:
"source_ip": string,
"destination_ip": string,
"sent_bytes": integer,
- "pattern": string, # (null if not set)
+ "pattern": string, # null if not set
"destination": string,
"timestamp": float,
"response_bytes": integer,
@@ -44,10 +44,12 @@ Schema:
"packets_received": integer,
"packet_loss_percent": float,
"duplicates": integer,
- "round_trip_ms_min": float,
- "round_trip_ms_avg": float,
- "round_trip_ms_max": float,
- "round_trip_ms_stddev": float,
+ "errors": integer, # null if not set
+ "corrupted": integer, # null if not set
+ "round_trip_ms_min": float, # null if not set
+ "round_trip_ms_avg": float, # null if not set
+ "round_trip_ms_max": float, # null if not set
+ "round_trip_ms_stddev": float, # null if not set
# below object only exists if using -qq or ignore_exceptions=True
"_jc_meta": {
@@ -74,6 +76,7 @@ Examples:
{"type":"reply","destination_ip":"1.1.1.1","sent_bytes":"56","patte...}
...
"""
+import re
import string
import ipaddress
import jc.utils
@@ -85,7 +88,7 @@ from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.3'
+ version = '1.4'
description = '`ping` and `ping6` command streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -110,13 +113,14 @@ def _process(proc_data):
Dictionary. Structured data to conform to the schema.
"""
int_list = {
- 'sent_bytes', 'packets_transmitted', 'packets_received', 'response_bytes', 'icmp_seq',
- 'ttl', 'duplicates', 'vr', 'hl', 'tos', 'len', 'id', 'flg', 'off', 'pro', 'cks'
+ 'sent_bytes', 'packets_transmitted', 'packets_received',
+ 'response_bytes', 'icmp_seq', 'ttl', 'duplicates', 'vr', 'hl', 'tos',
+ 'len', 'id', 'flg', 'off', 'pro', 'cks', 'errors', 'corrupted'
}
float_list = {
- 'packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max',
- 'round_trip_ms_stddev', 'timestamp', 'time_ms'
+ 'packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg',
+ 'round_trip_ms_max', 'round_trip_ms_stddev', 'timestamp', 'time_ms'
}
for key in proc_data:
@@ -144,6 +148,12 @@ class _state:
packet_loss_percent = None
time_ms = None
duplicates = None
+ corrupted = None
+ errors = None
+ round_trip_ms_min = None
+ round_trip_ms_avg = None
+ round_trip_ms_max = None
+ round_trip_ms_stddev = None
def _ipv6_in(line):
@@ -369,24 +379,44 @@ def _linux_parse(line, s):
return None
if s.footer:
- if 'packets transmitted' in line:
- if ' duplicates,' in line:
- s.packets_transmitted = line.split()[0]
- s.packets_received = line.split()[3]
- s.packet_loss_percent = line.split()[7].rstrip('%')
- s.duplicates = line.split()[5].lstrip('+')
- s.time_ms = line.split()[11].replace('ms', '')
- return None
+ #
+ # See: https://github.com/dgibson/iputils/blob/master/ping_common.c#L995
+ #
+ m = re.search(r'(\d+) packets transmitted', line)
+ if m:
+ s.packets_transmitted = m.group(1)
- s.packets_transmitted = line.split()[0]
- s.packets_received = line.split()[3]
- s.packet_loss_percent = line.split()[5].rstrip('%')
- s.duplicates = '0'
- s.time_ms = line.split()[9].replace('ms', '')
- return None
+ m = re.search(r'(\d+) received,', line)
+ if m:
+ s.packets_received = m.group(1)
+
+ m = re.search(r'[+](\d+) duplicates', line)
+ if m:
+ s.duplicates = m.group(1)
+
+ m = re.search(r'[+](\d+) corrupted', line)
+ if m:
+ s.corrupted = m.group(1)
+
+ m = re.search(r'[+](\d+) errors', line)
+ if m:
+ s.errors = m.group(1)
+
+ m = re.search(r'([\d\.]+)% packet loss', line)
+ if m:
+ s.packet_loss_percent = m.group(1)
+
+ m = re.search(r'time (\d+)ms', line)
+ if m:
+ s.time_ms = m.group(1)
+
+ m = re.search(r'rtt min\/avg\/max\/mdev += +([\d\.]+)\/([\d\.]+)\/([\d\.]+)\/([\d\.]+) ms', line)
+ if m:
+ s.round_trip_ms_min = m.group(1)
+ s.round_trip_ms_avg = m.group(2)
+ s.round_trip_ms_max = m.group(3)
+ s.round_trip_ms_stddev = m.group(4)
- split_line = line.split(' = ')[1]
- split_line = split_line.split('/')
output_line = {
'type': 'summary',
'destination_ip': s.destination_ip or None,
@@ -394,15 +424,16 @@ def _linux_parse(line, s):
'pattern': s.pattern or None,
'packets_transmitted': s.packets_transmitted or None,
'packets_received': s.packets_received or None,
- 'packet_loss_percent': s.packet_loss_percent or None,
- 'duplicates': s.duplicates or None,
- 'time_ms': s.time_ms or None,
- 'round_trip_ms_min': split_line[0],
- 'round_trip_ms_avg': split_line[1],
- 'round_trip_ms_max': split_line[2],
- 'round_trip_ms_stddev': split_line[3].split()[0]
+ 'packet_loss_percent': s.packet_loss_percent,
+ 'duplicates': s.duplicates or '0',
+ 'errors': s.errors,
+ 'corrupted': s.corrupted,
+ 'time_ms': s.time_ms,
+ 'round_trip_ms_min': s.round_trip_ms_min,
+ 'round_trip_ms_avg': s.round_trip_ms_avg,
+ 'round_trip_ms_max': s.round_trip_ms_max,
+ 'round_trip_ms_stddev': s.round_trip_ms_stddev
}
-
return output_line
# ping response lines
@@ -488,6 +519,7 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
streaming_input_type_check(data)
s = _state()
+ summary_obj = {}
for line in data:
try:
@@ -528,6 +560,12 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
if s.os_detected and s.linux:
output_line = _linux_parse(line, s)
+ # summary can be multiple lines so don't output until the end
+ if output_line:
+ if output_line.get('type', None) == 'summary':
+ summary_obj = output_line
+ continue
+
elif s.os_detected and s.bsd:
output_line = _bsd_parse(line, s)
@@ -542,3 +580,10 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
except Exception as e:
yield raise_or_yield(ignore_exceptions, e, line)
+
+ # yield summary, if it exists
+ try:
+ if summary_obj:
+ yield summary_obj if raw else _process(summary_obj)
+ except Exception as e:
+ yield raise_or_yield(ignore_exceptions, e, str(summary_obj))
diff --git a/jc/parsers/route.py b/jc/parsers/route.py
index b9590ee6..d6ae5a42 100644
--- a/jc/parsers/route.py
+++ b/jc/parsers/route.py
@@ -214,7 +214,7 @@ def parse(data, raw=False, quiet=False):
if jc.utils.has_data(data):
import jc.parsers.route_windows
- if cleandata[0] in jc.parsers.route_windows.SEPERATORS:
+ if cleandata[0] in jc.parsers.route_windows.SEPARATORS:
raw_output = jc.parsers.route_windows.parse(cleandata)
else:
cleandata.pop(0) # Removing "Kernel IP routing table".
diff --git a/jc/parsers/route_windows.py b/jc/parsers/route_windows.py
index 19f7c142..46a8cbf7 100644
--- a/jc/parsers/route_windows.py
+++ b/jc/parsers/route_windows.py
@@ -6,7 +6,7 @@
import re
from typing import List
-SEPERATORS = (
+SEPARATORS = (
"===========================================================================",
" None"
)
@@ -24,7 +24,7 @@ ROUTE_TYPES = ("Active Routes:", "Persistent Routes:")
def get_lines_until_seperator(iterator):
lines = []
for line in iterator:
- if line in SEPERATORS:
+ if line in SEPARATORS:
break
lines.append(line)
return lines
@@ -86,7 +86,7 @@ def parse(cleandata: List[str]):
interfaces = []
for interface_line in data_iterator:
interface_line = interface_line.strip()
- if interface_line in SEPERATORS:
+ if interface_line in SEPARATORS:
break
interface_match = INTERFACE_REGEX.search(interface_line)
diff --git a/jc/parsers/ver.py b/jc/parsers/ver.py
index 43126804..b4e5fd61 100644
--- a/jc/parsers/ver.py
+++ b/jc/parsers/ver.py
@@ -2,7 +2,7 @@
Best-effort attempt to parse various styles of version numbers. This parser
is based off of the version parser included in the CPython distutils
-libary.
+library.
If the version string conforms to some de facto-standard versioning rules
followed by many developers a `strict` key will be present in the output
diff --git a/jc/parsers/x509_cert.py b/jc/parsers/x509_cert.py
index 501f0059..8381638e 100644
--- a/jc/parsers/x509_cert.py
+++ b/jc/parsers/x509_cert.py
@@ -413,7 +413,7 @@ from jc.parsers.asn1crypto import pem, x509, jc_global
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.2'
+ version = '1.3'
description = 'X.509 PEM and DER certificate file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -477,7 +477,10 @@ def _fix_objects(obj):
# according to the spec this field can be string or integer
if isinstance(v, int):
v_str = str(v)
- v_hex = _b2a(_i2b(v))
+ if v < 0:
+ v_hex = "(Negative)" + _b2a(_i2b(abs(v)))
+ else:
+ v_hex = _b2a(_i2b(v))
else:
v_str = str(v)
v_hex = _b2a(v_str.encode())
diff --git a/jc/parsers/xml.py b/jc/parsers/xml.py
index a54de22c..d8393a68 100644
--- a/jc/parsers/xml.py
+++ b/jc/parsers/xml.py
@@ -81,7 +81,7 @@ except Exception:
class info():
"""Provides parser metadata (version, author, etc.)"""
- version = '1.7'
+ version = '1.8'
description = 'XML file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -105,13 +105,18 @@ def _process(proc_data, has_data=False):
Dictionary representing an XML document.
"""
- raw_output = []
+ proc_output = []
if has_data:
# standard output with @ prefix for attributes
- raw_output = xmltodict.parse(proc_data, dict_constructor=dict)
+ try:
+ proc_output = xmltodict.parse(proc_data,
+ dict_constructor=dict,
+ process_comments=True)
+ except ValueError:
+ proc_output = xmltodict.parse(proc_data, dict_constructor=dict)
- return raw_output
+ return proc_output
def parse(data, raw=False, quiet=False):
@@ -137,10 +142,17 @@ def parse(data, raw=False, quiet=False):
if jc.utils.has_data(data):
has_data = True
- if raw:
- if has_data:
- # modified output with _ prefix for attributes
- raw_output = xmltodict.parse(data, dict_constructor=dict, attr_prefix='_')
+ if raw and has_data:
+ # modified output with _ prefix for attributes
+ try:
+ raw_output = xmltodict.parse(data,
+ dict_constructor=dict,
+ process_comments=True,
+ attr_prefix='_')
+ except ValueError:
+ raw_output = xmltodict.parse(data,
+ dict_constructor=dict,
+ attr_prefix='_')
return raw_output
diff --git a/jc/parsers/xrandr.py b/jc/parsers/xrandr.py
index 363741f9..dfd480bf 100644
--- a/jc/parsers/xrandr.py
+++ b/jc/parsers/xrandr.py
@@ -26,8 +26,8 @@ Schema:
"current_height": integer,
"maximum_width": integer,
"maximum_height": integer,
- "associated_device": {
- "associated_modes": [
+ "devices": {
+ "modes": [
{
"resolution_width": integer,
"resolution_height": integer,
@@ -58,24 +58,6 @@ Schema:
"reflection": string
}
],
- "unassociated_devices": [
- {
- "associated_modes": [
- {
- "resolution_width": integer,
- "resolution_height": integer,
- "is_high_resolution": boolean,
- "frequencies": [
- {
- "frequency": float,
- "is_current": boolean,
- "is_preferred": boolean
- }
- ]
- }
- ]
- }
- ]
}
Examples:
@@ -91,8 +73,8 @@ Examples:
"current_height": 1080,
"maximum_width": 32767,
"maximum_height": 32767,
- "associated_device": {
- "associated_modes": [
+ "devices": {
+ "modes": [
{
"resolution_width": 1920,
"resolution_height": 1080,
@@ -136,8 +118,7 @@ Examples:
"reflection": "normal"
}
}
- ],
- "unassociated_devices": []
+ ]
}
$ xrandr --properties | jc --xrandr -p
@@ -151,8 +132,8 @@ Examples:
"current_height": 1080,
"maximum_width": 32767,
"maximum_height": 32767,
- "associated_device": {
- "associated_modes": [
+ "devices": {
+ "modes": [
{
"resolution_width": 1920,
"resolution_height": 1080,
@@ -199,8 +180,7 @@ Examples:
"reflection": "normal"
}
}
- ],
- "unassociated_devices": []
+ ]
}
"""
import re
@@ -212,14 +192,15 @@ from jc.parsers.pyedid.helpers.edid_helper import EdidHelper
class info:
"""Provides parser metadata (version, author, etc.)"""
- version = "1.2"
+
+ version = "1.3"
description = "`xrandr` command parser"
author = "Kevin Lyter"
- author_email = "lyter_git at sent.com"
- details = 'Using parts of the pyedid library at https://github.com/jojonas/pyedid.'
+ author_email = "code (at) lyterk.com"
+ details = "Using parts of the pyedid library at https://github.com/jojonas/pyedid."
compatible = ["linux", "darwin", "cygwin", "aix", "freebsd"]
magic_commands = ["xrandr"]
- tags = ['command']
+ tags = ["command"]
__version__ = info.version
@@ -267,7 +248,7 @@ try:
"offset_height": int,
"dimension_width": int,
"dimension_height": int,
- "associated_modes": List[Mode],
+ "modes": List[Mode],
"rotation": str,
"reflection": str,
},
@@ -282,14 +263,13 @@ try:
"current_height": int,
"maximum_width": int,
"maximum_height": int,
- "associated_device": Device,
+ "devices": List[Device],
},
)
Response = TypedDict(
"Response",
{
"screens": List[Screen],
- "unassociated_devices": List[Device],
},
)
except ImportError:
@@ -317,14 +297,17 @@ def _parse_screen(next_lines: List[str]) -> Optional[Screen]:
return None
raw_matches = result.groupdict()
- screen: Screen = {}
+
+ screen: Screen = {"devices": []}
for k, v in raw_matches.items():
screen[k] = int(v)
- if next_lines:
+ while next_lines:
device: Optional[Device] = _parse_device(next_lines)
- if device:
- screen["associated_device"] = device
+ if not device:
+ break
+ else:
+ screen["devices"].append(device)
return screen
@@ -358,7 +341,7 @@ def _parse_device(next_lines: List[str], quiet: bool = False) -> Optional[Device
matches = result.groupdict()
device: Device = {
- "associated_modes": [],
+ "modes": [],
"is_connected": matches["is_connected"] == "connected",
"is_primary": matches["is_primary"] is not None
and len(matches["is_primary"]) > 0,
@@ -367,14 +350,21 @@ def _parse_device(next_lines: List[str], quiet: bool = False) -> Optional[Device
"reflection": matches["reflection"] or "normal",
}
for k, v in matches.items():
- if k not in {"is_connected", "is_primary", "device_name", "rotation", "reflection"}:
+ if k not in {
+ "is_connected",
+ "is_primary",
+ "device_name",
+ "rotation",
+ "reflection",
+ }:
try:
if v:
device[k] = int(v)
- except ValueError and not quiet:
- jc.utils.warning_message(
- [f"{next_line} : {k} - {v} is not int-able"]
- )
+ except ValueError:
+ if not quiet:
+ jc.utils.warning_message(
+ [f"{next_line} : {k} - {v} is not int-able"]
+ )
model: Optional[Model] = _parse_model(next_lines, quiet)
if model:
@@ -386,7 +376,7 @@ def _parse_device(next_lines: List[str], quiet: bool = False) -> Optional[Device
next_line = next_lines.pop()
next_mode: Optional[Mode] = _parse_mode(next_line)
if next_mode:
- device["associated_modes"].append(next_mode)
+ device["modes"].append(next_mode)
else:
if re.match(_device_pattern, next_line):
next_lines.append(next_line)
@@ -481,7 +471,7 @@ def _parse_mode(line: str) -> Optional[Mode]:
return mode
-def parse(data: str, raw: bool =False, quiet: bool =False) -> Dict:
+def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict:
"""
Main text parsing function
@@ -500,19 +490,12 @@ def parse(data: str, raw: bool =False, quiet: bool =False) -> Dict:
linedata = data.splitlines()
linedata.reverse() # For popping
- result: Response = {"screens": [], "unassociated_devices": []}
+ result: Response = {"screens": []}
if jc.utils.has_data(data):
while linedata:
screen = _parse_screen(linedata)
if screen:
result["screens"].append(screen)
- else:
- device = _parse_device(linedata, quiet)
- if device:
- result["unassociated_devices"].append(device)
-
- if not result["unassociated_devices"] and not result["screens"]:
- return {}
return result
diff --git a/man/jc.1 b/man/jc.1
index c1581d05..fe86eb59 100644
--- a/man/jc.1
+++ b/man/jc.1
@@ -1,4 +1,4 @@
-.TH jc 1 2023-07-30 1.23.4 "JSON Convert"
+.TH jc 1 2023-10-21 1.23.5 "JSON Convert"
.SH NAME
\fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types,
and strings
@@ -267,6 +267,11 @@ hashsum command parser (`md5sum`, `shasum`, etc.)
\fB--history\fP
`history` command parser
+.TP
+.B
+\fB--host\fP
+`host` command parser
+
.TP
.B
\fB--hosts\fP
@@ -372,6 +377,11 @@ Key/Value file and string parser
\fB--lsattr\fP
`lsattr` command parser
+.TP
+.B
+\fB--lsb-release\fP
+`lsb_release` command parser
+
.TP
.B
\fB--lsblk\fP
@@ -432,6 +442,11 @@ M3U and M3U8 file parser
\fB--nmcli\fP
`nmcli` command parser
+.TP
+.B
+\fB--nsd-control\fP
+`nsd-control` command parser
+
.TP
.B
\fB--ntpq\fP
@@ -447,6 +462,11 @@ openvpn-status.log file parser
\fB--os-prober\fP
`os-prober` command parser
+.TP
+.B
+\fB--os-release\fP
+`/etc/os-release` file parser
+
.TP
.B
\fB--passwd\fP
diff --git a/setup.py b/setup.py
index dc15a04a..cade05ee 100755
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
setuptools.setup(
name='jc',
- version='1.23.4',
+ version='1.23.5',
author='Kelly Brazil',
author_email='kellyjonbrazil@gmail.com',
description='Converts the output of popular command-line tools and file-types to JSON.',
diff --git a/tests/fixtures/centos-7.7/ping-hostname-O-D-p-s-streaming.json b/tests/fixtures/centos-7.7/ping-hostname-O-D-p-s-streaming.json
index 8dba0fa9..add74f7b 100644
--- a/tests/fixtures/centos-7.7/ping-hostname-O-D-p-s-streaming.json
+++ b/tests/fixtures/centos-7.7/ping-hostname-O-D-p-s-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978465.914536,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":31.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978465.993009,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":30.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978467.010196,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":32.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978468.033743,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":38.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978469.051227,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":38.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978470.048764,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978471.051945,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":28.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978472.064206,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978473.062587,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":31.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978474.074343,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":38.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978475.079703,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":38.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978476.076383,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978477.084119,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978478.092207,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":31.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978479.104358,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":15,"ttl":59,"time_ms":37.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978480.106907,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":37.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978481.11558,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":37.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978482.119872,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":33.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978483.131901,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":37.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978484.141117,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":36.9,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19146.0,"round_trip_ms_min":28.96,"round_trip_ms_avg":34.468,"round_trip_ms_max":38.892,"round_trip_ms_stddev":3.497}]
+[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978465.914536,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":31.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978465.993009,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":30.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978467.010196,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":32.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978468.033743,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":38.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978469.051227,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":38.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978470.048764,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978471.051945,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":28.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978472.064206,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978473.062587,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":31.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978474.074343,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":38.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978475.079703,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":38.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978476.076383,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978477.084119,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978478.092207,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":31.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978479.104358,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":15,"ttl":59,"time_ms":37.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978480.106907,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":37.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978481.11558,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":37.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978482.119872,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":33.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978483.131901,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":37.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978484.141117,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":36.9,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19146.0,"round_trip_ms_min":28.96,"round_trip_ms_avg":34.468,"round_trip_ms_max":38.892,"round_trip_ms_stddev":3.497}]
diff --git a/tests/fixtures/centos-7.7/ping-hostname-O-p-streaming.json b/tests/fixtures/centos-7.7/ping-hostname-O-p-streaming.json
index 1301f8c4..d9fc04ad 100644
--- a/tests/fixtures/centos-7.7/ping-hostname-O-p-streaming.json
+++ b/tests/fixtures/centos-7.7/ping-hostname-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":1,"ttl":59,"time_ms":24.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":2,"ttl":59,"time_ms":23.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":3,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":4,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":5,"ttl":59,"time_ms":26.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":6,"ttl":59,"time_ms":24.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":7,"ttl":59,"time_ms":24.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":8,"ttl":59,"time_ms":33.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":9,"ttl":59,"time_ms":32.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":10,"ttl":59,"time_ms":31.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":11,"ttl":59,"time_ms":25.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":12,"ttl":59,"time_ms":33.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":13,"ttl":59,"time_ms":23.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":14,"ttl":59,"time_ms":23.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":15,"ttl":59,"time_ms":33.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":16,"ttl":59,"time_ms":24.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":17,"ttl":59,"time_ms":30.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":18,"ttl":59,"time_ms":24.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":19,"ttl":59,"time_ms":32.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":20,"ttl":59,"time_ms":31.0,"duplicate":false},{"type":"summary","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19233.0,"round_trip_ms_min":23.359,"round_trip_ms_avg":28.495,"round_trip_ms_max":33.979,"round_trip_ms_stddev":4.081}]
+[{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":1,"ttl":59,"time_ms":24.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":2,"ttl":59,"time_ms":23.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":3,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":4,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":5,"ttl":59,"time_ms":26.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":6,"ttl":59,"time_ms":24.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":7,"ttl":59,"time_ms":24.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":8,"ttl":59,"time_ms":33.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":9,"ttl":59,"time_ms":32.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":10,"ttl":59,"time_ms":31.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":11,"ttl":59,"time_ms":25.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":12,"ttl":59,"time_ms":33.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":13,"ttl":59,"time_ms":23.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":14,"ttl":59,"time_ms":23.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":15,"ttl":59,"time_ms":33.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":16,"ttl":59,"time_ms":24.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":17,"ttl":59,"time_ms":30.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":18,"ttl":59,"time_ms":24.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":19,"ttl":59,"time_ms":32.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":20,"ttl":59,"time_ms":31.0,"duplicate":false},{"type":"summary","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19233.0,"round_trip_ms_min":23.359,"round_trip_ms_avg":28.495,"round_trip_ms_max":33.979,"round_trip_ms_stddev":4.081}]
diff --git a/tests/fixtures/centos-7.7/ping-hostname-O-streaming.json b/tests/fixtures/centos-7.7/ping-hostname-O-streaming.json
index 100da291..9d651eba 100644
--- a/tests/fixtures/centos-7.7/ping-hostname-O-streaming.json
+++ b/tests/fixtures/centos-7.7/ping-hostname-O-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":29.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":30.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":35.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":35.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":27.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":28.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":35.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":35.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":35.5,"duplicate":false},{"type":"timeout","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":15},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":36.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":36.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":34.3,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"time_ms":19125.0,"round_trip_ms_min":27.656,"round_trip_ms_avg":33.717,"round_trip_ms_max":36.758,"round_trip_ms_stddev":2.814}]
+[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":29.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":30.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":35.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":35.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":27.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":28.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":35.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":35.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":35.5,"duplicate":false},{"type":"timeout","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":15},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":36.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":36.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":34.3,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19125.0,"round_trip_ms_min":27.656,"round_trip_ms_avg":33.717,"round_trip_ms_max":36.758,"round_trip_ms_stddev":2.814}]
diff --git a/tests/fixtures/centos-7.7/ping-ip-O-D-streaming.json b/tests/fixtures/centos-7.7/ping-ip-O-D-streaming.json
index 81495252..99878475 100644
--- a/tests/fixtures/centos-7.7/ping-ip-O-D-streaming.json
+++ b/tests/fixtures/centos-7.7/ping-ip-O-D-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037214.261953,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.041,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037215.264798,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.048,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037216.272296,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.047,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037217.275851,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.062,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037218.284242,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037219.283712,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037220.290949,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037221.295962,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037222.30702,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.048,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037223.313919,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.081,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037224.313679,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037225.320748,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037226.324322,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037227.325835,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037228.327028,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037229.329891,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.052,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037230.333891,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037231.338137,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037232.340475,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.048,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037233.343058,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19081.0,"round_trip_ms_min":0.041,"round_trip_ms_avg":0.048,"round_trip_ms_max":0.081,"round_trip_ms_stddev":0.009}]
+[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037214.261953,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.041,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037215.264798,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.048,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037216.272296,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.047,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037217.275851,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.062,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037218.284242,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037219.283712,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037220.290949,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037221.295962,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037222.30702,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.048,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037223.313919,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.081,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037224.313679,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037225.320748,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037226.324322,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037227.325835,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037228.327028,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037229.329891,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.052,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037230.333891,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037231.338137,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037232.340475,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.048,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595037233.343058,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19081.0,"round_trip_ms_min":0.041,"round_trip_ms_avg":0.048,"round_trip_ms_max":0.081,"round_trip_ms_stddev":0.009}]
diff --git a/tests/fixtures/centos-7.7/ping-ip-O-streaming-ignore-exceptions.json b/tests/fixtures/centos-7.7/ping-ip-O-streaming-ignore-exceptions.json
index d4013c22..9240d076 100644
--- a/tests/fixtures/centos-7.7/ping-ip-O-streaming-ignore-exceptions.json
+++ b/tests/fixtures/centos-7.7/ping-ip-O-streaming-ignore-exceptions.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.038,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.043,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.044,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.052,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.08,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.043,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.047,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.04,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.052,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.044,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.043,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.043,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.05,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.045,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.062,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.046,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.046,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.045,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.044,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.044,"duplicate":false,"_jc_meta":{"success":true}},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19070.0,"round_trip_ms_min":0.038,"round_trip_ms_avg":0.047,"round_trip_ms_max":0.08,"round_trip_ms_stddev":0.011,"_jc_meta":{"success":true}}]
+[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.038,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.043,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.044,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.052,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.08,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.043,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.047,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.04,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.052,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.044,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.043,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.043,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.05,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.045,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.062,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.046,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.046,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.045,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.044,"duplicate":false,"_jc_meta":{"success":true}},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.044,"duplicate":false,"_jc_meta":{"success":true}},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19070.0,"round_trip_ms_min":0.038,"round_trip_ms_avg":0.047,"round_trip_ms_max":0.08,"round_trip_ms_stddev":0.011,"_jc_meta":{"success":true}}]
diff --git a/tests/fixtures/centos-7.7/ping-ip-O-streaming.json b/tests/fixtures/centos-7.7/ping-ip-O-streaming.json
index 53be94ea..17af3756 100644
--- a/tests/fixtures/centos-7.7/ping-ip-O-streaming.json
+++ b/tests/fixtures/centos-7.7/ping-ip-O-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.038,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.052,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.08,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.047,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.04,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.052,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.062,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19070.0,"round_trip_ms_min":0.038,"round_trip_ms_avg":0.047,"round_trip_ms_max":0.08,"round_trip_ms_stddev":0.011}]
+[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.038,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.052,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.08,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.047,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.04,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.052,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.062,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.046,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.045,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.044,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19070.0,"round_trip_ms_min":0.038,"round_trip_ms_avg":0.047,"round_trip_ms_max":0.08,"round_trip_ms_stddev":0.011}]
diff --git a/tests/fixtures/centos-7.7/ping-ip-dup-streaming.json b/tests/fixtures/centos-7.7/ping-ip-dup-streaming.json
index 771c20f6..ad169e16 100644
--- a/tests/fixtures/centos-7.7/ping-ip-dup-streaming.json
+++ b/tests/fixtures/centos-7.7/ping-ip-dup-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.221","icmp_seq":1,"ttl":64,"time_ms":0.586,"duplicate":false},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.88","icmp_seq":1,"ttl":64,"time_ms":382.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.78","icmp_seq":1,"ttl":128,"time_ms":382.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.217","icmp_seq":1,"ttl":255,"time_ms":387.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.186","icmp_seq":1,"ttl":64,"time_ms":389.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.89","icmp_seq":1,"ttl":64,"time_ms":389.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.75","icmp_seq":1,"ttl":64,"time_ms":584.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.221","icmp_seq":2,"ttl":64,"time_ms":0.861,"duplicate":false},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.78","icmp_seq":2,"ttl":128,"time_ms":4.17,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.88","icmp_seq":2,"ttl":64,"time_ms":4.19,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.89","icmp_seq":2,"ttl":64,"time_ms":12.7,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.81","icmp_seq":1,"ttl":64,"time_ms":1029.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.72","icmp_seq":1,"ttl":64,"time_ms":1276.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.251","icmp_seq":1,"ttl":64,"time_ms":1276.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.251","icmp_seq":2,"ttl":64,"time_ms":262.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.72","icmp_seq":2,"ttl":64,"time_ms":263.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.246","icmp_seq":2,"ttl":255,"time_ms":263.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.217","icmp_seq":2,"ttl":255,"time_ms":919.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.186","icmp_seq":2,"ttl":64,"time_ms":919.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.75","icmp_seq":2,"ttl":64,"time_ms":919.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.81","icmp_seq":2,"ttl":64,"time_ms":919.0,"duplicate":true},{"type":"summary","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"packets_transmitted":2,"packets_received":2,"packet_loss_percent":0.0,"duplicates":19,"time_ms":1013.0,"round_trip_ms_min":0.586,"round_trip_ms_avg":504.26,"round_trip_ms_max":1276.448,"round_trip_ms_stddev":417.208}]
+[{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.221","icmp_seq":1,"ttl":64,"time_ms":0.586,"duplicate":false},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.88","icmp_seq":1,"ttl":64,"time_ms":382.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.78","icmp_seq":1,"ttl":128,"time_ms":382.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.217","icmp_seq":1,"ttl":255,"time_ms":387.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.186","icmp_seq":1,"ttl":64,"time_ms":389.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.89","icmp_seq":1,"ttl":64,"time_ms":389.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.75","icmp_seq":1,"ttl":64,"time_ms":584.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.221","icmp_seq":2,"ttl":64,"time_ms":0.861,"duplicate":false},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.78","icmp_seq":2,"ttl":128,"time_ms":4.17,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.88","icmp_seq":2,"ttl":64,"time_ms":4.19,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.89","icmp_seq":2,"ttl":64,"time_ms":12.7,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.81","icmp_seq":1,"ttl":64,"time_ms":1029.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.72","icmp_seq":1,"ttl":64,"time_ms":1276.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.251","icmp_seq":1,"ttl":64,"time_ms":1276.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.251","icmp_seq":2,"ttl":64,"time_ms":262.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.72","icmp_seq":2,"ttl":64,"time_ms":263.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.246","icmp_seq":2,"ttl":255,"time_ms":263.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.217","icmp_seq":2,"ttl":255,"time_ms":919.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.186","icmp_seq":2,"ttl":64,"time_ms":919.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.75","icmp_seq":2,"ttl":64,"time_ms":919.0,"duplicate":true},{"type":"reply","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"192.168.1.81","icmp_seq":2,"ttl":64,"time_ms":919.0,"duplicate":true},{"type":"summary","destination_ip":"192.168.1.255","sent_bytes":56,"pattern":null,"packets_transmitted":2,"packets_received":2,"packet_loss_percent":0.0,"duplicates":19,"errors":null,"corrupted":null,"time_ms":1013.0,"round_trip_ms_min":0.586,"round_trip_ms_avg":504.26,"round_trip_ms_max":1276.448,"round_trip_ms_stddev":417.208}]
diff --git a/tests/fixtures/centos-7.7/ping-missing-hostname-streaming.json b/tests/fixtures/centos-7.7/ping-missing-hostname-streaming.json
index df17a394..f02848bf 100644
--- a/tests/fixtures/centos-7.7/ping-missing-hostname-streaming.json
+++ b/tests/fixtures/centos-7.7/ping-missing-hostname-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"100.68.105.124","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"100.68.105.124","icmp_seq":1,"ttl":64,"time_ms":0.04,"duplicate":false},{"type":"summary","destination_ip":"100.68.105.124","sent_bytes":56,"pattern":null,"packets_transmitted":1,"packets_received":1,"packet_loss_percent":0.0,"duplicates":0,"time_ms":0.0,"round_trip_ms_min":0.04,"round_trip_ms_avg":0.04,"round_trip_ms_max":0.04,"round_trip_ms_stddev":0.0}]
+[{"type":"reply","destination_ip":"100.68.105.124","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"100.68.105.124","icmp_seq":1,"ttl":64,"time_ms":0.04,"duplicate":false},{"type":"summary","destination_ip":"100.68.105.124","sent_bytes":56,"pattern":null,"packets_transmitted":1,"packets_received":1,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":0.0,"round_trip_ms_min":0.04,"round_trip_ms_avg":0.04,"round_trip_ms_max":0.04,"round_trip_ms_stddev":0.0}]
diff --git a/tests/fixtures/centos-7.7/ping6-hostname-O-D-p-s-streaming.json b/tests/fixtures/centos-7.7/ping6-hostname-O-D-p-s-streaming.json
index b5bdb549..de215038 100644
--- a/tests/fixtures/centos-7.7/ping6-hostname-O-D-p-s-streaming.json
+++ b/tests/fixtures/centos-7.7/ping6-hostname-O-D-p-s-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978345.609669,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":1,"ttl":59,"time_ms":32.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978346.58542,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":2,"ttl":59,"time_ms":39.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978347.594128,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":3,"ttl":59,"time_ms":42.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978348.595221,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":4,"ttl":59,"time_ms":40.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978349.600372,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":5,"ttl":59,"time_ms":43.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978350.590676,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":6,"ttl":59,"time_ms":31.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978351.601527,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":7,"ttl":59,"time_ms":41.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978352.604195,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":8,"ttl":59,"time_ms":41.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978353.607212,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":9,"ttl":59,"time_ms":42.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978354.610771,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":10,"ttl":59,"time_ms":40.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978355.613729,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":11,"ttl":59,"time_ms":40.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978356.611887,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":12,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978357.62481,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":13,"ttl":59,"time_ms":40.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978358.629185,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":14,"ttl":59,"time_ms":42.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978359.634854,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":15,"ttl":59,"time_ms":41.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978360.638344,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":16,"ttl":59,"time_ms":40.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978361.640968,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":17,"ttl":59,"time_ms":40.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978362.645739,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":18,"ttl":59,"time_ms":39.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978363.6467,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":19,"ttl":59,"time_ms":37.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978364.650853,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":20,"ttl":59,"time_ms":33.6,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19077.0,"round_trip_ms_min":31.845,"round_trip_ms_avg":39.274,"round_trip_ms_max":43.243,"round_trip_ms_stddev":3.522}]
+[{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978345.609669,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":1,"ttl":59,"time_ms":32.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978346.58542,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":2,"ttl":59,"time_ms":39.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978347.594128,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":3,"ttl":59,"time_ms":42.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978348.595221,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":4,"ttl":59,"time_ms":40.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978349.600372,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":5,"ttl":59,"time_ms":43.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978350.590676,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":6,"ttl":59,"time_ms":31.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978351.601527,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":7,"ttl":59,"time_ms":41.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978352.604195,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":8,"ttl":59,"time_ms":41.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978353.607212,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":9,"ttl":59,"time_ms":42.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978354.610771,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":10,"ttl":59,"time_ms":40.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978355.613729,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":11,"ttl":59,"time_ms":40.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978356.611887,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":12,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978357.62481,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":13,"ttl":59,"time_ms":40.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978358.629185,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":14,"ttl":59,"time_ms":42.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978359.634854,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":15,"ttl":59,"time_ms":41.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978360.638344,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":16,"ttl":59,"time_ms":40.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978361.640968,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":17,"ttl":59,"time_ms":40.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978362.645739,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":18,"ttl":59,"time_ms":39.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978363.6467,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":19,"ttl":59,"time_ms":37.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1594978364.650853,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":20,"ttl":59,"time_ms":33.6,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19077.0,"round_trip_ms_min":31.845,"round_trip_ms_avg":39.274,"round_trip_ms_max":43.243,"round_trip_ms_stddev":3.522}]
diff --git a/tests/fixtures/centos-7.7/ping6-hostname-O-p-streaming.json b/tests/fixtures/centos-7.7/ping6-hostname-O-p-streaming.json
index e3a5b4fe..b15a0dd4 100644
--- a/tests/fixtures/centos-7.7/ping6-hostname-O-p-streaming.json
+++ b/tests/fixtures/centos-7.7/ping6-hostname-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":1,"ttl":59,"time_ms":30.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":2,"ttl":59,"time_ms":39.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":3,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":4,"ttl":59,"time_ms":38.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":5,"ttl":59,"time_ms":38.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":6,"ttl":59,"time_ms":42.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":7,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":8,"ttl":59,"time_ms":39.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":9,"ttl":59,"time_ms":39.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":10,"ttl":59,"time_ms":38.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":11,"ttl":59,"time_ms":38.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":12,"ttl":59,"time_ms":38.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":13,"ttl":59,"time_ms":39.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":14,"ttl":59,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":15,"ttl":59,"time_ms":33.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":16,"ttl":59,"time_ms":39.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":17,"ttl":59,"time_ms":38.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":18,"ttl":59,"time_ms":41.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":19,"ttl":59,"time_ms":32.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":20,"ttl":59,"time_ms":38.4,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19164.0,"round_trip_ms_min":30.757,"round_trip_ms_avg":37.455,"round_trip_ms_max":42.652,"round_trip_ms_stddev":3.338}]
+[{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":1,"ttl":59,"time_ms":30.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":2,"ttl":59,"time_ms":39.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":3,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":4,"ttl":59,"time_ms":38.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":5,"ttl":59,"time_ms":38.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":6,"ttl":59,"time_ms":42.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":7,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":8,"ttl":59,"time_ms":39.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":9,"ttl":59,"time_ms":39.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":10,"ttl":59,"time_ms":38.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":11,"ttl":59,"time_ms":38.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":12,"ttl":59,"time_ms":38.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":13,"ttl":59,"time_ms":39.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":14,"ttl":59,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":15,"ttl":59,"time_ms":33.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":16,"ttl":59,"time_ms":39.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":17,"ttl":59,"time_ms":38.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":18,"ttl":59,"time_ms":41.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":19,"ttl":59,"time_ms":32.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":20,"ttl":59,"time_ms":38.4,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19164.0,"round_trip_ms_min":30.757,"round_trip_ms_avg":37.455,"round_trip_ms_max":42.652,"round_trip_ms_stddev":3.338}]
diff --git a/tests/fixtures/centos-7.7/ping6-ip-O-D-p-streaming.json b/tests/fixtures/centos-7.7/ping6-ip-O-D-p-streaming.json
index f9221923..a2d0079c 100644
--- a/tests/fixtures/centos-7.7/ping6-ip-O-D-p-streaming.json
+++ b/tests/fixtures/centos-7.7/ping6-ip-O-D-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976827.240914,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":28.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976828.25493,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":37.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976829.252877,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":29.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976830.262654,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":37.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976831.265626,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":34.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976832.269834,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":35.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976833.268059,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976834.274292,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":28.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976835.287123,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976836.287707,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976837.290589,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":11,"ttl":59,"time_ms":35.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976838.293514,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":35.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976839.290914,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":29.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976840.292897,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":28.5,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976842.269238,"icmp_seq":15},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976842.30145,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":31.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976843.312998,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":39.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976844.314228,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":35.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976845.315518,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":35.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976846.321706,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":35.4,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"time_ms":19074.0,"round_trip_ms_min":28.15,"round_trip_ms_avg":33.534,"round_trip_ms_max":39.843,"round_trip_ms_stddev":3.489}]
+[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976827.240914,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":28.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976828.25493,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":37.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976829.252877,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":29.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976830.262654,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":37.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976831.265626,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":34.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976832.269834,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":35.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976833.268059,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976834.274292,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":28.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976835.287123,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976836.287707,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976837.290589,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":11,"ttl":59,"time_ms":35.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976838.293514,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":35.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976839.290914,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":29.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976840.292897,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":28.5,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976842.269238,"icmp_seq":15},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976842.30145,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":31.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976843.312998,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":39.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976844.314228,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":35.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976845.315518,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":35.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1594976846.321706,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":35.4,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19074.0,"round_trip_ms_min":28.15,"round_trip_ms_avg":33.534,"round_trip_ms_max":39.843,"round_trip_ms_stddev":3.489}]
diff --git a/tests/fixtures/centos-7.7/ping6-ip-O-p-streaming.json b/tests/fixtures/centos-7.7/ping6-ip-O-p-streaming.json
index 394184db..810937c5 100644
--- a/tests/fixtures/centos-7.7/ping6-ip-O-p-streaming.json
+++ b/tests/fixtures/centos-7.7/ping6-ip-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":27.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":36.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":28.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":28.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":36.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":36.3,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":11},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":36.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":35.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":36.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":37.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":36.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":27.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":38.1,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"time_ms":19067.0,"round_trip_ms_min":27.064,"round_trip_ms_avg":33.626,"round_trip_ms_max":38.146,"round_trip_ms_stddev":3.803}]
+[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":27.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":36.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":28.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":28.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":36.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":36.3,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":11},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":36.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":35.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":36.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":37.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":36.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":27.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":38.1,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19067.0,"round_trip_ms_min":27.064,"round_trip_ms_avg":33.626,"round_trip_ms_max":38.146,"round_trip_ms_stddev":3.803}]
diff --git a/tests/fixtures/centos-7.7/ping6-ip-dup-streaming.json b/tests/fixtures/centos-7.7/ping6-ip-dup-streaming.json
index 8361d359..575bb4b0 100644
--- a/tests/fixtures/centos-7.7/ping6-ip-dup-streaming.json
+++ b/tests/fixtures/centos-7.7/ping6-ip-dup-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":1,"ttl":64,"time_ms":0.245,"duplicate":false},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::feae:34ff:fea1:3a80%ens33","icmp_seq":1,"ttl":64,"time_ms":3.65,"duplicate":true},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":2,"ttl":64,"time_ms":0.329,"duplicate":false},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::feae:34ff:fea1:3a80%ens33","icmp_seq":2,"ttl":64,"time_ms":11.7,"duplicate":true},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":3,"ttl":64,"time_ms":0.592,"duplicate":false},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::feae:34ff:fea1:3a80%ens33","icmp_seq":3,"ttl":64,"time_ms":12.3,"duplicate":true},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":4,"ttl":64,"time_ms":0.51,"duplicate":false},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::feae:34ff:fea1:3a80%ens33","icmp_seq":4,"ttl":64,"time_ms":12.5,"duplicate":true},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":5,"ttl":64,"time_ms":0.538,"duplicate":false},{"type":"summary","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"packets_transmitted":5,"packets_received":5,"packet_loss_percent":0.0,"duplicates":4,"time_ms":4017.0,"round_trip_ms_min":0.245,"round_trip_ms_avg":4.726,"round_trip_ms_max":12.568,"round_trip_ms_stddev":5.395}]
+[{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":1,"ttl":64,"time_ms":0.245,"duplicate":false},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::feae:34ff:fea1:3a80%ens33","icmp_seq":1,"ttl":64,"time_ms":3.65,"duplicate":true},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":2,"ttl":64,"time_ms":0.329,"duplicate":false},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::feae:34ff:fea1:3a80%ens33","icmp_seq":2,"ttl":64,"time_ms":11.7,"duplicate":true},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":3,"ttl":64,"time_ms":0.592,"duplicate":false},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::feae:34ff:fea1:3a80%ens33","icmp_seq":3,"ttl":64,"time_ms":12.3,"duplicate":true},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":4,"ttl":64,"time_ms":0.51,"duplicate":false},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::feae:34ff:fea1:3a80%ens33","icmp_seq":4,"ttl":64,"time_ms":12.5,"duplicate":true},{"type":"reply","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"fe80::c48:5896:526d:81ba%ens33","icmp_seq":5,"ttl":64,"time_ms":0.538,"duplicate":false},{"type":"summary","destination_ip":"ff02::1%ens33","sent_bytes":56,"pattern":null,"packets_transmitted":5,"packets_received":5,"packet_loss_percent":0.0,"duplicates":4,"errors":null,"corrupted":null,"time_ms":4017.0,"round_trip_ms_min":0.245,"round_trip_ms_avg":4.726,"round_trip_ms_max":12.568,"round_trip_ms_stddev":5.395}]
diff --git a/tests/fixtures/fedora32/ping-hostname-O-D-p-s-streaming.json b/tests/fixtures/fedora32/ping-hostname-O-D-p-s-streaming.json
index a1167559..fb447205 100644
--- a/tests/fixtures/fedora32/ping-hostname-O-D-p-s-streaming.json
+++ b/tests/fixtures/fedora32/ping-hostname-O-D-p-s-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191335.548399,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":1,"ttl":59,"time_ms":46.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191336.134174,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":2,"ttl":59,"time_ms":61.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191337.101575,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":3,"ttl":59,"time_ms":26.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191338.108023,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":4,"ttl":59,"time_ms":30.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191339.229213,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":5,"ttl":59,"time_ms":149.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191340.114026,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":6,"ttl":59,"time_ms":32.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191341.122628,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":7,"ttl":59,"time_ms":37.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191342.110785,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":8,"ttl":59,"time_ms":26.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191343.118652,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":9,"ttl":59,"time_ms":32.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191344.1303,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":10,"ttl":59,"time_ms":43.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191345.162284,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":11,"ttl":59,"time_ms":71.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191346.123086,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":12,"ttl":59,"time_ms":31.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191347.127689,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":13,"ttl":59,"time_ms":33.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191348.142817,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":14,"ttl":59,"time_ms":45.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191349.125383,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":15,"ttl":59,"time_ms":25.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191350.136294,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":16,"ttl":59,"time_ms":34.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191351.135889,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":17,"ttl":59,"time_ms":31.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191352.134199,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":18,"ttl":59,"time_ms":26.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191353.147391,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":19,"ttl":59,"time_ms":38.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191354.15064,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":20,"ttl":59,"time_ms":39.5,"duplicate":false},{"type":"summary","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19040.0,"round_trip_ms_min":25.934,"round_trip_ms_avg":43.176,"round_trip_ms_max":149.271,"round_trip_ms_stddev":26.937}]
+[{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191335.548399,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":1,"ttl":59,"time_ms":46.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191336.134174,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":2,"ttl":59,"time_ms":61.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191337.101575,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":3,"ttl":59,"time_ms":26.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191338.108023,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":4,"ttl":59,"time_ms":30.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191339.229213,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":5,"ttl":59,"time_ms":149.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191340.114026,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":6,"ttl":59,"time_ms":32.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191341.122628,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":7,"ttl":59,"time_ms":37.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191342.110785,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":8,"ttl":59,"time_ms":26.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191343.118652,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":9,"ttl":59,"time_ms":32.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191344.1303,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":10,"ttl":59,"time_ms":43.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191345.162284,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":11,"ttl":59,"time_ms":71.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191346.123086,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":12,"ttl":59,"time_ms":31.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191347.127689,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":13,"ttl":59,"time_ms":33.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191348.142817,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":14,"ttl":59,"time_ms":45.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191349.125383,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":15,"ttl":59,"time_ms":25.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191350.136294,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":16,"ttl":59,"time_ms":34.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191351.135889,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":17,"ttl":59,"time_ms":31.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191352.134199,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":18,"ttl":59,"time_ms":26.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191353.147391,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":19,"ttl":59,"time_ms":38.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191354.15064,"response_bytes":1408,"response_ip":"151.101.129.67","icmp_seq":20,"ttl":59,"time_ms":39.5,"duplicate":false},{"type":"summary","destination_ip":"151.101.129.67","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19040.0,"round_trip_ms_min":25.934,"round_trip_ms_avg":43.176,"round_trip_ms_max":149.271,"round_trip_ms_stddev":26.937}]
diff --git a/tests/fixtures/fedora32/ping-hostname-O-p-streaming.json b/tests/fixtures/fedora32/ping-hostname-O-p-streaming.json
index 4ce9962c..d3943f20 100644
--- a/tests/fixtures/fedora32/ping-hostname-O-p-streaming.json
+++ b/tests/fixtures/fedora32/ping-hostname-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":1,"ttl":56,"time_ms":38.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":2,"ttl":56,"time_ms":38.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":3,"ttl":56,"time_ms":39.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":4,"ttl":56,"time_ms":49.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":5,"ttl":56,"time_ms":47.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":6,"ttl":56,"time_ms":48.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":7,"ttl":56,"time_ms":53.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":8,"ttl":56,"time_ms":47.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":9,"ttl":56,"time_ms":47.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":10,"ttl":56,"time_ms":51.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":11,"ttl":56,"time_ms":55.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":12,"ttl":56,"time_ms":40.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":13,"ttl":56,"time_ms":39.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":14,"ttl":56,"time_ms":40.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":15,"ttl":56,"time_ms":41.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":16,"ttl":56,"time_ms":57.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":17,"ttl":56,"time_ms":45.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":18,"ttl":56,"time_ms":39.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":19,"ttl":56,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":20,"ttl":56,"time_ms":40.4,"duplicate":false},{"type":"summary","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19026.0,"round_trip_ms_min":37.406,"round_trip_ms_avg":44.894,"round_trip_ms_max":57.881,"round_trip_ms_stddev":6.101}]
+[{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":1,"ttl":56,"time_ms":38.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":2,"ttl":56,"time_ms":38.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":3,"ttl":56,"time_ms":39.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":4,"ttl":56,"time_ms":49.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":5,"ttl":56,"time_ms":47.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":6,"ttl":56,"time_ms":48.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":7,"ttl":56,"time_ms":53.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":8,"ttl":56,"time_ms":47.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":9,"ttl":56,"time_ms":47.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":10,"ttl":56,"time_ms":51.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":11,"ttl":56,"time_ms":55.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":12,"ttl":56,"time_ms":40.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":13,"ttl":56,"time_ms":39.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":14,"ttl":56,"time_ms":40.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":15,"ttl":56,"time_ms":41.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":16,"ttl":56,"time_ms":57.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":17,"ttl":56,"time_ms":45.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":18,"ttl":56,"time_ms":39.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":19,"ttl":56,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.197.67","icmp_seq":20,"ttl":56,"time_ms":40.4,"duplicate":false},{"type":"summary","destination_ip":"151.101.197.67","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19026.0,"round_trip_ms_min":37.406,"round_trip_ms_avg":44.894,"round_trip_ms_max":57.881,"round_trip_ms_stddev":6.101}]
diff --git a/tests/fixtures/fedora32/ping-hostname-O-streaming.json b/tests/fixtures/fedora32/ping-hostname-O-streaming.json
index d80b926d..4fe37e88 100644
--- a/tests/fixtures/fedora32/ping-hostname-O-streaming.json
+++ b/tests/fixtures/fedora32/ping-hostname-O-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":1,"ttl":59,"time_ms":27.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":2,"ttl":59,"time_ms":31.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":3,"ttl":59,"time_ms":25.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":4,"ttl":59,"time_ms":65.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":5,"ttl":59,"time_ms":32.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":6,"ttl":59,"time_ms":32.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":7,"ttl":59,"time_ms":156.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":8,"ttl":59,"time_ms":216.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":9,"ttl":59,"time_ms":275.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":10,"ttl":59,"time_ms":25.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":11,"ttl":59,"time_ms":29.5,"duplicate":false},{"type":"timeout","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":12},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":13,"ttl":59,"time_ms":25.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":14,"ttl":59,"time_ms":33.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":15,"ttl":59,"time_ms":24.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":16,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":17,"ttl":59,"time_ms":24.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":18,"ttl":59,"time_ms":34.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":19,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":20,"ttl":59,"time_ms":45.8,"duplicate":false},{"type":"summary","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"time_ms":19075.0,"round_trip_ms_min":24.317,"round_trip_ms_avg":61.577,"round_trip_ms_max":274.537,"round_trip_ms_stddev":69.94}]
+[{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":1,"ttl":59,"time_ms":27.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":2,"ttl":59,"time_ms":31.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":3,"ttl":59,"time_ms":25.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":4,"ttl":59,"time_ms":65.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":5,"ttl":59,"time_ms":32.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":6,"ttl":59,"time_ms":32.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":7,"ttl":59,"time_ms":156.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":8,"ttl":59,"time_ms":216.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":9,"ttl":59,"time_ms":275.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":10,"ttl":59,"time_ms":25.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":11,"ttl":59,"time_ms":29.5,"duplicate":false},{"type":"timeout","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":12},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":13,"ttl":59,"time_ms":25.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":14,"ttl":59,"time_ms":33.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":15,"ttl":59,"time_ms":24.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":16,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":17,"ttl":59,"time_ms":24.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":18,"ttl":59,"time_ms":34.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":19,"ttl":59,"time_ms":30.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.129.67","icmp_seq":20,"ttl":59,"time_ms":45.8,"duplicate":false},{"type":"summary","destination_ip":"151.101.129.67","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19075.0,"round_trip_ms_min":24.317,"round_trip_ms_avg":61.577,"round_trip_ms_max":274.537,"round_trip_ms_stddev":69.94}]
diff --git a/tests/fixtures/fedora32/ping-ip-O-D-streaming.json b/tests/fixtures/fedora32/ping-ip-O-D-streaming.json
index f53c6f3e..a98719bd 100644
--- a/tests/fixtures/fedora32/ping-ip-O-D-streaming.json
+++ b/tests/fixtures/fedora32/ping-ip-O-D-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191373.643436,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191374.662543,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.083,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191375.685291,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.091,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191376.709678,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.092,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191377.734105,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191378.758107,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191379.781215,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.087,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191380.80601,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.092,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191381.829806,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.088,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191382.853166,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.135,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191383.876966,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.101,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191384.900636,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.084,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191385.925055,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.071,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191386.94986,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.087,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191387.973041,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.087,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191388.997049,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.073,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191390.021265,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.074,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191391.044904,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191392.069285,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191393.093307,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.084,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19450.0,"round_trip_ms_min":0.043,"round_trip_ms_avg":0.086,"round_trip_ms_max":0.135,"round_trip_ms_stddev":0.016}]
+[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191373.643436,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191374.662543,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.083,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191375.685291,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.091,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191376.709678,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.092,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191377.734105,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191378.758107,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191379.781215,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.087,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191380.80601,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.092,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191381.829806,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.088,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191382.853166,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.135,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191383.876966,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.101,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191384.900636,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.084,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191385.925055,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.071,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191386.94986,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.087,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191387.973041,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.087,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191388.997049,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.073,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191390.021265,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.074,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191391.044904,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191392.069285,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595191393.093307,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.084,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19450.0,"round_trip_ms_min":0.043,"round_trip_ms_avg":0.086,"round_trip_ms_max":0.135,"round_trip_ms_stddev":0.016}]
diff --git a/tests/fixtures/fedora32/ping-ip-O-streaming.json b/tests/fixtures/fedora32/ping-ip-O-streaming.json
index 3c2d6bec..c771335c 100644
--- a/tests/fixtures/fedora32/ping-ip-O-streaming.json
+++ b/tests/fixtures/fedora32/ping-ip-O-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.07,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.093,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.078,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.16,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.155,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.084,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.111,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.079,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.103,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.105,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.087,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.081,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.092,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19480.0,"round_trip_ms_min":0.043,"round_trip_ms_avg":0.093,"round_trip_ms_max":0.16,"round_trip_ms_stddev":0.025}]
+[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.07,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.093,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.078,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.16,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.155,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.084,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.111,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.079,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.103,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.105,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.087,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.081,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.089,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.09,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.092,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19480.0,"round_trip_ms_min":0.043,"round_trip_ms_avg":0.093,"round_trip_ms_max":0.16,"round_trip_ms_stddev":0.025}]
diff --git a/tests/fixtures/fedora32/ping6-hostname-O-D-p-s-streaming.json b/tests/fixtures/fedora32/ping6-hostname-O-D-p-s-streaming.json
index 6333c1ec..16020d48 100644
--- a/tests/fixtures/fedora32/ping6-hostname-O-D-p-s-streaming.json
+++ b/tests/fixtures/fedora32/ping6-hostname-O-D-p-s-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191433.391154,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":1,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191434.063086,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":2,"ttl":59,"time_ms":37.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191435.071905,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":3,"ttl":59,"time_ms":44.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191436.067128,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":4,"ttl":59,"time_ms":37.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191437.06455,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":5,"ttl":59,"time_ms":32.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191438.06541,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":6,"ttl":59,"time_ms":30.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191439.076718,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":7,"ttl":59,"time_ms":40.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191440.076357,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":8,"ttl":59,"time_ms":38.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191441.079078,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":9,"ttl":59,"time_ms":39.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191442.077537,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":10,"ttl":59,"time_ms":34.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191443.104345,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":11,"ttl":59,"time_ms":59.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191444.083741,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":12,"ttl":59,"time_ms":36.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191445.086748,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":13,"ttl":59,"time_ms":37.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191446.088958,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":14,"ttl":59,"time_ms":37.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191447.086122,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":15,"ttl":59,"time_ms":30.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191448.088312,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":16,"ttl":59,"time_ms":30.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191449.098353,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":17,"ttl":59,"time_ms":38.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191450.09959,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":18,"ttl":59,"time_ms":38.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191451.10105,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":19,"ttl":59,"time_ms":37.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191452.100239,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":20,"ttl":59,"time_ms":35.0,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19042.0,"round_trip_ms_min":30.757,"round_trip_ms_avg":37.536,"round_trip_ms_max":59.021,"round_trip_ms_stddev":5.967}]
+[{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191433.391154,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":1,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191434.063086,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":2,"ttl":59,"time_ms":37.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191435.071905,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":3,"ttl":59,"time_ms":44.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191436.067128,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":4,"ttl":59,"time_ms":37.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191437.06455,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":5,"ttl":59,"time_ms":32.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191438.06541,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":6,"ttl":59,"time_ms":30.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191439.076718,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":7,"ttl":59,"time_ms":40.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191440.076357,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":8,"ttl":59,"time_ms":38.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191441.079078,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":9,"ttl":59,"time_ms":39.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191442.077537,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":10,"ttl":59,"time_ms":34.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191443.104345,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":11,"ttl":59,"time_ms":59.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191444.083741,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":12,"ttl":59,"time_ms":36.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191445.086748,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":13,"ttl":59,"time_ms":37.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191446.088958,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":14,"ttl":59,"time_ms":37.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191447.086122,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":15,"ttl":59,"time_ms":30.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191448.088312,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":16,"ttl":59,"time_ms":30.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191449.098353,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":17,"ttl":59,"time_ms":38.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191450.09959,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":18,"ttl":59,"time_ms":38.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191451.10105,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":19,"ttl":59,"time_ms":37.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595191452.100239,"response_bytes":1408,"response_ip":"2a04:4e42:200::323","icmp_seq":20,"ttl":59,"time_ms":35.0,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:200::323","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19042.0,"round_trip_ms_min":30.757,"round_trip_ms_avg":37.536,"round_trip_ms_max":59.021,"round_trip_ms_stddev":5.967}]
diff --git a/tests/fixtures/fedora32/ping6-hostname-O-p-streaming.json b/tests/fixtures/fedora32/ping6-hostname-O-p-streaming.json
index 27ee1ef5..e72338f9 100644
--- a/tests/fixtures/fedora32/ping6-hostname-O-p-streaming.json
+++ b/tests/fixtures/fedora32/ping6-hostname-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":1,"ttl":59,"time_ms":24.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":2,"ttl":59,"time_ms":30.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":3,"ttl":59,"time_ms":23.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":4,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":5,"ttl":59,"time_ms":32.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":6,"ttl":59,"time_ms":32.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":7,"ttl":59,"time_ms":26.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":8,"ttl":59,"time_ms":31.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":9,"ttl":59,"time_ms":33.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":10,"ttl":59,"time_ms":32.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":11,"ttl":59,"time_ms":31.0,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":12},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":13,"ttl":59,"time_ms":31.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":14,"ttl":59,"time_ms":112.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":15,"ttl":59,"time_ms":162.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":16,"ttl":59,"time_ms":223.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":17,"ttl":59,"time_ms":281.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":18,"ttl":59,"time_ms":33.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":19,"ttl":59,"time_ms":32.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":20,"ttl":59,"time_ms":42.3,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"time_ms":19049.0,"round_trip_ms_min":23.598,"round_trip_ms_avg":65.877,"round_trip_ms_max":281.064,"round_trip_ms_stddev":72.64}]
+[{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":1,"ttl":59,"time_ms":24.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":2,"ttl":59,"time_ms":30.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":3,"ttl":59,"time_ms":23.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":4,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":5,"ttl":59,"time_ms":32.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":6,"ttl":59,"time_ms":32.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":7,"ttl":59,"time_ms":26.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":8,"ttl":59,"time_ms":31.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":9,"ttl":59,"time_ms":33.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":10,"ttl":59,"time_ms":32.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":11,"ttl":59,"time_ms":31.0,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":12},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":13,"ttl":59,"time_ms":31.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":14,"ttl":59,"time_ms":112.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":15,"ttl":59,"time_ms":162.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":16,"ttl":59,"time_ms":223.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":17,"ttl":59,"time_ms":281.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":18,"ttl":59,"time_ms":33.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":19,"ttl":59,"time_ms":32.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:400::323","icmp_seq":20,"ttl":59,"time_ms":42.3,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:400::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19049.0,"round_trip_ms_min":23.598,"round_trip_ms_avg":65.877,"round_trip_ms_max":281.064,"round_trip_ms_stddev":72.64}]
diff --git a/tests/fixtures/fedora32/ping6-ip-O-D-p-streaming.json b/tests/fixtures/fedora32/ping6-ip-O-D-p-streaming.json
index 4ea93903..c30ec9d9 100644
--- a/tests/fixtures/fedora32/ping6-ip-O-D-p-streaming.json
+++ b/tests/fixtures/fedora32/ping6-ip-O-D-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191413.333769,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191414.342973,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":41.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191415.332214,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":28.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191416.342603,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":36.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191417.344996,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":37.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191418.348619,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":37.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191419.357154,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":44.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191420.350087,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":35.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191421.346691,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191422.355843,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191423.397934,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":11,"ttl":59,"time_ms":76.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191424.470798,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":148.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191425.358652,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":33.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191426.404587,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":77.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191427.359785,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":29.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191428.367539,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191429.372551,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":37.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191430.364571,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":27.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191431.375232,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":37.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191432.375802,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":34.3,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19042.0,"round_trip_ms_min":27.88,"round_trip_ms_avg":45.072,"round_trip_ms_max":148.38,"round_trip_ms_stddev":27.078}]
+[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191413.333769,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191414.342973,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":41.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191415.332214,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":28.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191416.342603,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":36.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191417.344996,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":37.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191418.348619,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":37.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191419.357154,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":44.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191420.350087,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":35.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191421.346691,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191422.355843,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":37.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191423.397934,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":11,"ttl":59,"time_ms":76.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191424.470798,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":148.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191425.358652,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":33.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191426.404587,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":77.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191427.359785,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":29.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191428.367539,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191429.372551,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":37.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191430.364571,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":27.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191431.375232,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":37.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595191432.375802,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":34.3,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19042.0,"round_trip_ms_min":27.88,"round_trip_ms_avg":45.072,"round_trip_ms_max":148.38,"round_trip_ms_stddev":27.078}]
diff --git a/tests/fixtures/fedora32/ping6-ip-O-p-streaming.json b/tests/fixtures/fedora32/ping6-ip-O-p-streaming.json
index a5647996..a0a17372 100644
--- a/tests/fixtures/fedora32/ping6-ip-O-p-streaming.json
+++ b/tests/fixtures/fedora32/ping6-ip-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":36.6,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":3},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":28.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":36.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":28.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":39.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":28.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":28.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":36.5,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":11},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":33.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":28.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":27.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":36.0,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":16},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":26.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":38.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":43.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":37.9,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":17,"packet_loss_percent":15.0,"duplicates":0,"time_ms":19193.0,"round_trip_ms_min":26.566,"round_trip_ms_avg":33.623,"round_trip_ms_max":43.945,"round_trip_ms_stddev":5.029}]
+[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":36.6,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":3},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":28.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":36.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":28.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":39.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":28.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":28.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":36.5,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":11},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":33.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":28.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":27.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":36.0,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":16},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":26.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":38.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":43.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":37.9,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":17,"packet_loss_percent":15.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19193.0,"round_trip_ms_min":26.566,"round_trip_ms_avg":33.623,"round_trip_ms_max":43.945,"round_trip_ms_stddev":5.029}]
diff --git a/tests/fixtures/generic/env-multiline-raw.json b/tests/fixtures/generic/env-multiline-raw.json
new file mode 100644
index 00000000..9d311a66
--- /dev/null
+++ b/tests/fixtures/generic/env-multiline-raw.json
@@ -0,0 +1 @@
+{"TERM_PROGRAM":"Apple_Terminal","SHELL":"/bin/zsh","TERM":"xterm-256color","TMPDIR":"/var/folders/8g/r6tdh9kj6z35x9rfmgtt3x6r0000gn/T/","TERM_PROGRAM_VERSION":"447","TERM_SESSION_ID":"A7F0FFB1-C12A-42EA-A8D9-0757BB2D4DDE","USER":"kelly","SSH_AUTH_SOCK":"/private/tmp/com.apple.launchd.6IQJQijqVl/Listeners","PATH":"/Users/kelly/.pyenv/shims:/Users/kelly/.gem/ruby/2.6.0/bin:/Users/kelly/.local/bin:/Users/kelly/.cargo/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin","LaunchInstanceID":"3D00D30B-5C8B-421F-958D-91B196167506","__CFBundleIdentifier":"com.apple.Terminal","PWD":"/Users/kelly/temp","XPC_FLAGS":"0x0","XPC_SERVICE_NAME":"0","SHLVL":"1","HOME":"/Users/kelly","LOGNAME":"kelly","SECURITYSESSIONID":"186a3","OLDPWD":"/Users/kelly/git/jc/tests/fixtures/ubuntu-22.04","JC_COLORS":"cyan,default,default,default","JELLO_COLORS":"cyan,default,default,default","PYENV_ROOT":"/Users/kelly/.pyenv","PYENV_SHELL":"zsh","MYVAR":"hello world","hello":"world","KELLYVAR":"This is a multiline\nvariable that has var=1 a definition\ninside of it","LANG":"en_US.UTF-8","_":"/usr/bin/env"}
diff --git a/tests/fixtures/generic/env-multiline.json b/tests/fixtures/generic/env-multiline.json
new file mode 100644
index 00000000..5abf6fe3
--- /dev/null
+++ b/tests/fixtures/generic/env-multiline.json
@@ -0,0 +1 @@
+[{"name":"TERM_PROGRAM","value":"Apple_Terminal"},{"name":"SHELL","value":"/bin/zsh"},{"name":"TERM","value":"xterm-256color"},{"name":"TMPDIR","value":"/var/folders/8g/r6tdh9kj6z35x9rfmgtt3x6r0000gn/T/"},{"name":"TERM_PROGRAM_VERSION","value":"447"},{"name":"TERM_SESSION_ID","value":"A7F0FFB1-C12A-42EA-A8D9-0757BB2D4DDE"},{"name":"USER","value":"kelly"},{"name":"SSH_AUTH_SOCK","value":"/private/tmp/com.apple.launchd.6IQJQijqVl/Listeners"},{"name":"PATH","value":"/Users/kelly/.pyenv/shims:/Users/kelly/.gem/ruby/2.6.0/bin:/Users/kelly/.local/bin:/Users/kelly/.cargo/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin"},{"name":"LaunchInstanceID","value":"3D00D30B-5C8B-421F-958D-91B196167506"},{"name":"__CFBundleIdentifier","value":"com.apple.Terminal"},{"name":"PWD","value":"/Users/kelly/temp"},{"name":"XPC_FLAGS","value":"0x0"},{"name":"XPC_SERVICE_NAME","value":"0"},{"name":"SHLVL","value":"1"},{"name":"HOME","value":"/Users/kelly"},{"name":"LOGNAME","value":"kelly"},{"name":"SECURITYSESSIONID","value":"186a3"},{"name":"OLDPWD","value":"/Users/kelly/git/jc/tests/fixtures/ubuntu-22.04"},{"name":"JC_COLORS","value":"cyan,default,default,default"},{"name":"JELLO_COLORS","value":"cyan,default,default,default"},{"name":"PYENV_ROOT","value":"/Users/kelly/.pyenv"},{"name":"PYENV_SHELL","value":"zsh"},{"name":"MYVAR","value":"hello world"},{"name":"hello","value":"world"},{"name":"KELLYVAR","value":"This is a multiline\nvariable that has var=1 a definition\ninside of it"},{"name":"LANG","value":"en_US.UTF-8"},{"name":"_","value":"/usr/bin/env"}]
diff --git a/tests/fixtures/generic/env-multiline.out b/tests/fixtures/generic/env-multiline.out
new file mode 100644
index 00000000..9ddc021f
--- /dev/null
+++ b/tests/fixtures/generic/env-multiline.out
@@ -0,0 +1,30 @@
+TERM_PROGRAM=Apple_Terminal
+SHELL=/bin/zsh
+TERM=xterm-256color
+TMPDIR=/var/folders/8g/r6tdh9kj6z35x9rfmgtt3x6r0000gn/T/
+TERM_PROGRAM_VERSION=447
+TERM_SESSION_ID=A7F0FFB1-C12A-42EA-A8D9-0757BB2D4DDE
+USER=kelly
+SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.6IQJQijqVl/Listeners
+PATH=/Users/kelly/.pyenv/shims:/Users/kelly/.gem/ruby/2.6.0/bin:/Users/kelly/.local/bin:/Users/kelly/.cargo/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin
+LaunchInstanceID=3D00D30B-5C8B-421F-958D-91B196167506
+__CFBundleIdentifier=com.apple.Terminal
+PWD=/Users/kelly/temp
+XPC_FLAGS=0x0
+XPC_SERVICE_NAME=0
+SHLVL=1
+HOME=/Users/kelly
+LOGNAME=kelly
+SECURITYSESSIONID=186a3
+OLDPWD=/Users/kelly/git/jc/tests/fixtures/ubuntu-22.04
+JC_COLORS=cyan,default,default,default
+JELLO_COLORS=cyan,default,default,default
+PYENV_ROOT=/Users/kelly/.pyenv
+PYENV_SHELL=zsh
+MYVAR=hello world
+hello=world
+KELLYVAR=This is a multiline
+variable that has var=1 a definition
+inside of it
+LANG=en_US.UTF-8
+_=/usr/bin/env
diff --git a/tests/fixtures/generic/host-google.json b/tests/fixtures/generic/host-google.json
new file mode 100644
index 00000000..149bf4f9
--- /dev/null
+++ b/tests/fixtures/generic/host-google.json
@@ -0,0 +1 @@
+[{"hostname":"google.com","address":["142.250.179.206"],"v6-address":["2a00:1450:400e:811::200e"],"mail":["smtp.google.com."]}]
diff --git a/tests/fixtures/generic/host-google.out b/tests/fixtures/generic/host-google.out
new file mode 100644
index 00000000..009113f7
--- /dev/null
+++ b/tests/fixtures/generic/host-google.out
@@ -0,0 +1,3 @@
+google.com has address 142.250.179.206
+google.com has IPv6 address 2a00:1450:400e:811::200e
+google.com mail is handled by 10 smtp.google.com.
diff --git a/tests/fixtures/generic/host-sunet.json b/tests/fixtures/generic/host-sunet.json
new file mode 100644
index 00000000..49f14529
--- /dev/null
+++ b/tests/fixtures/generic/host-sunet.json
@@ -0,0 +1 @@
+[{"nameserver":"192.36.125.2","zone":"sunet.se","mname":"hidden-master.sunet.se.","rname":"hostmaster.sunet.se.","serial":2023091102,"refresh":28800,"retry":7200,"expire":604800,"minimum":300},{"nameserver":"193.10.252.19","zone":"sunet.se","mname":"hidden-master.sunet.se.","rname":"hostmaster.sunet.se.","serial":2023091102,"refresh":28800,"retry":7200,"expire":604800,"minimum":300},{"nameserver":"2001:6b0:1::250","zone":"sunet.se","mname":"hidden-master.sunet.se.","rname":"hostmaster.sunet.se.","serial":2023091102,"refresh":28800,"retry":7200,"expire":604800,"minimum":300},{"nameserver":"2001:948:4:2::19","zone":"sunet.se","mname":"hidden-master.sunet.se.","rname":"hostmaster.sunet.se.","serial":2023091102,"refresh":28800,"retry":7200,"expire":604800,"minimum":300},{"nameserver":"2001:6b0:5a:4020::384","zone":"sunet.se","mname":"hidden-master.sunet.se.","rname":"hostmaster.sunet.se.","serial":2023091102,"refresh":28800,"retry":7200,"expire":604800,"minimum":300},{"nameserver":"130.237.72.250","zone":"sunet.se","mname":"hidden-master.sunet.se.","rname":"hostmaster.sunet.se.","serial":2023091102,"refresh":28800,"retry":7200,"expire":604800,"minimum":300},{"nameserver":"2001:6b0:7::2","zone":"sunet.se","mname":"hidden-master.sunet.se.","rname":"hostmaster.sunet.se.","serial":2023091102,"refresh":28800,"retry":7200,"expire":604800,"minimum":300},{"nameserver":"89.47.185.240","zone":"sunet.se","mname":"hidden-master.sunet.se.","rname":"hostmaster.sunet.se.","serial":2023091102,"refresh":28800,"retry":7200,"expire":604800,"minimum":300}]
diff --git a/tests/fixtures/generic/host-sunet.out b/tests/fixtures/generic/host-sunet.out
new file mode 100644
index 00000000..e8f6e178
--- /dev/null
+++ b/tests/fixtures/generic/host-sunet.out
@@ -0,0 +1,16 @@
+Nameserver 192.36.125.2:
+ sunet.se has SOA record hidden-master.sunet.se. hostmaster.sunet.se. 2023091102 28800 7200 604800 300
+Nameserver 193.10.252.19:
+ sunet.se has SOA record hidden-master.sunet.se. hostmaster.sunet.se. 2023091102 28800 7200 604800 300
+Nameserver 2001:6b0:1::250:
+ sunet.se has SOA record hidden-master.sunet.se. hostmaster.sunet.se. 2023091102 28800 7200 604800 300
+Nameserver 2001:948:4:2::19:
+ sunet.se has SOA record hidden-master.sunet.se. hostmaster.sunet.se. 2023091102 28800 7200 604800 300
+Nameserver 2001:6b0:5a:4020::384:
+ sunet.se has SOA record hidden-master.sunet.se. hostmaster.sunet.se. 2023091102 28800 7200 604800 300
+Nameserver 130.237.72.250:
+ sunet.se has SOA record hidden-master.sunet.se. hostmaster.sunet.se. 2023091102 28800 7200 604800 300
+Nameserver 2001:6b0:7::2:
+ sunet.se has SOA record hidden-master.sunet.se. hostmaster.sunet.se. 2023091102 28800 7200 604800 300
+Nameserver 89.47.185.240:
+ sunet.se has SOA record hidden-master.sunet.se. hostmaster.sunet.se. 2023091102 28800 7200 604800 300
diff --git a/tests/fixtures/generic/lsb_release-a.json b/tests/fixtures/generic/lsb_release-a.json
new file mode 100644
index 00000000..a6963a3f
--- /dev/null
+++ b/tests/fixtures/generic/lsb_release-a.json
@@ -0,0 +1 @@
+{"Distributor ID":"Ubuntu","Description":"Ubuntu 16.04.6 LTS","Release":"16.04","Codename":"xenial"}
diff --git a/tests/fixtures/generic/lsb_release-a.out b/tests/fixtures/generic/lsb_release-a.out
new file mode 100644
index 00000000..78bc3113
--- /dev/null
+++ b/tests/fixtures/generic/lsb_release-a.out
@@ -0,0 +1,4 @@
+Distributor ID: Ubuntu
+Description: Ubuntu 16.04.6 LTS
+Release: 16.04
+Codename: xenial
diff --git a/tests/fixtures/generic/netstat-no-state.json b/tests/fixtures/generic/netstat-no-state.json
new file mode 100644
index 00000000..5f8e6150
--- /dev/null
+++ b/tests/fixtures/generic/netstat-no-state.json
@@ -0,0 +1 @@
+[{"proto":"udp","recv_q":0,"send_q":0,"local_address":"0.0.0.0","foreign_address":"0.0.0.0","state":null,"program_name":"avahi-daemon: r","kind":"network","pid":442,"local_port":"5353","foreign_port":"*","transport_protocol":"udp","network_protocol":"ipv4","local_port_num":5353},{"proto":"udp","recv_q":0,"send_q":0,"local_address":"0.0.0.0","foreign_address":"0.0.0.0","state":null,"program_name":"avahi-daemon: r","kind":"network","pid":442,"local_port":"49926","foreign_port":"*","transport_protocol":"udp","network_protocol":"ipv4","local_port_num":49926},{"proto":"udp6","recv_q":0,"send_q":0,"local_address":"::","foreign_address":"::","state":null,"program_name":"avahi-daemon: r","kind":"network","pid":442,"local_port":"5353","foreign_port":"*","transport_protocol":"udp","network_protocol":"ipv6","local_port_num":5353},{"proto":"udp6","recv_q":0,"send_q":0,"local_address":"::","foreign_address":"::","state":null,"program_name":"avahi-daemon: r","kind":"network","pid":442,"local_port":"35569","foreign_port":"*","transport_protocol":"udp","network_protocol":"ipv6","local_port_num":35569}]
diff --git a/tests/fixtures/generic/netstat-no-state.out b/tests/fixtures/generic/netstat-no-state.out
new file mode 100644
index 00000000..cabcff3f
--- /dev/null
+++ b/tests/fixtures/generic/netstat-no-state.out
@@ -0,0 +1,6 @@
+Active Internet connections (only servers)
+Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
+udp 0 0 0.0.0.0:5353 0.0.0.0:* 442/avahi-daemon: r
+udp 0 0 0.0.0.0:49926 0.0.0.0:* 442/avahi-daemon: r
+udp6 0 0 :::5353 :::* 442/avahi-daemon: r
+udp6 0 0 :::35569 :::* 442/avahi-daemon: r
diff --git a/tests/fixtures/generic/nsd_control-cookie_secrets.json b/tests/fixtures/generic/nsd_control-cookie_secrets.json
new file mode 100644
index 00000000..2de05ae8
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-cookie_secrets.json
@@ -0,0 +1 @@
+[{"active":"5414f1a7d8480347b4c01c806e9f442f","staging":"7b4c01c806e9f442f5414f1a7d848034"}]
diff --git a/tests/fixtures/generic/nsd_control-cookie_secrets.out b/tests/fixtures/generic/nsd_control-cookie_secrets.out
new file mode 100644
index 00000000..ca0ab231
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-cookie_secrets.out
@@ -0,0 +1,2 @@
+active : 5414f1a7d8480347b4c01c806e9f442f
+staging: 7b4c01c806e9f442f5414f1a7d848034
diff --git a/tests/fixtures/generic/nsd_control-stats.json b/tests/fixtures/generic/nsd_control-stats.json
new file mode 100644
index 00000000..a6bfc7eb
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-stats.json
@@ -0,0 +1 @@
+[{"server0.queries":109,"num.queries":109,"time.boot":456687.800773,"time.elapsed":18.508317,"size.db.disk":0,"size.db.mem":862619640,"size.xfrd.mem":4319184,"size.config.disk":0,"size.config.mem":1231920,"num.type.A":86,"num.type.NS":0,"num.type.MD":0,"num.type.MF":0,"num.type.CNAME":0,"num.type.SOA":9,"num.type.MB":0,"num.type.MG":0,"num.type.MR":0,"num.type.NULL":0,"num.type.WKS":0,"num.type.PTR":1,"num.type.HINFO":0,"num.type.MINFO":0,"num.type.MX":0,"num.type.TXT":10,"num.type.RP":0,"num.type.AFSDB":0,"num.type.X25":0,"num.type.ISDN":0,"num.type.RT":0,"num.type.NSAP":0,"num.type.SIG":0,"num.type.KEY":0,"num.type.PX":0,"num.type.AAAA":3,"num.type.LOC":0,"num.type.NXT":0,"num.type.SRV":0,"num.type.NAPTR":0,"num.type.KX":0,"num.type.CERT":0,"num.type.DNAME":0,"num.type.OPT":0,"num.type.APL":0,"num.type.DS":0,"num.type.SSHFP":0,"num.type.IPSECKEY":0,"num.type.RRSIG":0,"num.type.NSEC":0,"num.type.DNSKEY":0,"num.type.DHCID":0,"num.type.NSEC3":0,"num.type.NSEC3PARAM":0,"num.type.TLSA":0,"num.type.SMIMEA":0,"num.type.CDS":0,"num.type.CDNSKEY":0,"num.type.OPENPGPKEY":0,"num.type.CSYNC":0,"num.type.ZONEMD":0,"num.type.SVCB":0,"num.type.HTTPS":0,"num.type.SPF":0,"num.type.NID":0,"num.type.L32":0,"num.type.L64":0,"num.type.LP":0,"num.type.EUI48":0,"num.type.EUI64":0,"num.opcode.QUERY":100,"num.opcode.NOTIFY":9,"num.class.IN":109,"num.rcode.NOERROR":29,"num.rcode.FORMERR":0,"num.rcode.SERVFAIL":0,"num.rcode.NXDOMAIN":1,"num.rcode.NOTIMP":0,"num.rcode.REFUSED":79,"num.rcode.YXDOMAIN":0,"num.edns":19,"num.ednserr":0,"num.udp":41,"num.udp6":68,"num.tcp":0,"num.tcp6":0,"num.tls":0,"num.tls6":0,"num.answer_wo_aa":2,"num.rxerr":0,"num.txerr":0,"num.raxfr":0,"num.rixfr":0,"num.truncated":0,"num.dropped":0,"zone.master":0,"zone.slave":1}]
diff --git a/tests/fixtures/generic/nsd_control-stats.out b/tests/fixtures/generic/nsd_control-stats.out
new file mode 100644
index 00000000..f4c3b560
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-stats.out
@@ -0,0 +1,96 @@
+server0.queries=109
+num.queries=109
+time.boot=456687.800773
+time.elapsed=18.508317
+size.db.disk=0
+size.db.mem=862619640
+size.xfrd.mem=4319184
+size.config.disk=0
+size.config.mem=1231920
+num.type.A=86
+num.type.NS=0
+num.type.MD=0
+num.type.MF=0
+num.type.CNAME=0
+num.type.SOA=9
+num.type.MB=0
+num.type.MG=0
+num.type.MR=0
+num.type.NULL=0
+num.type.WKS=0
+num.type.PTR=1
+num.type.HINFO=0
+num.type.MINFO=0
+num.type.MX=0
+num.type.TXT=10
+num.type.RP=0
+num.type.AFSDB=0
+num.type.X25=0
+num.type.ISDN=0
+num.type.RT=0
+num.type.NSAP=0
+num.type.SIG=0
+num.type.KEY=0
+num.type.PX=0
+num.type.AAAA=3
+num.type.LOC=0
+num.type.NXT=0
+num.type.SRV=0
+num.type.NAPTR=0
+num.type.KX=0
+num.type.CERT=0
+num.type.DNAME=0
+num.type.OPT=0
+num.type.APL=0
+num.type.DS=0
+num.type.SSHFP=0
+num.type.IPSECKEY=0
+num.type.RRSIG=0
+num.type.NSEC=0
+num.type.DNSKEY=0
+num.type.DHCID=0
+num.type.NSEC3=0
+num.type.NSEC3PARAM=0
+num.type.TLSA=0
+num.type.SMIMEA=0
+num.type.CDS=0
+num.type.CDNSKEY=0
+num.type.OPENPGPKEY=0
+num.type.CSYNC=0
+num.type.ZONEMD=0
+num.type.SVCB=0
+num.type.HTTPS=0
+num.type.SPF=0
+num.type.NID=0
+num.type.L32=0
+num.type.L64=0
+num.type.LP=0
+num.type.EUI48=0
+num.type.EUI64=0
+num.opcode.QUERY=100
+num.opcode.NOTIFY=9
+num.class.IN=109
+num.rcode.NOERROR=29
+num.rcode.FORMERR=0
+num.rcode.SERVFAIL=0
+num.rcode.NXDOMAIN=1
+num.rcode.NOTIMP=0
+num.rcode.REFUSED=79
+num.rcode.YXDOMAIN=0
+num.edns=19
+num.ednserr=0
+num.udp=41
+num.udp6=68
+num.tcp=0
+num.tcp6=0
+num.tls=0
+num.tls6=0
+num.answer_wo_aa=2
+num.rxerr=0
+num.txerr=0
+num.raxfr=0
+num.rixfr=0
+num.truncated=0
+num.dropped=0
+zone.master=0
+zone.slave=1
diff --git a/tests/fixtures/generic/nsd_control-status.json b/tests/fixtures/generic/nsd_control-status.json
new file mode 100644
index 00000000..01e835aa
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-status.json
@@ -0,0 +1 @@
+[{"version":"4.6.2","verbosity":2,"ratelimit":0}]
diff --git a/tests/fixtures/generic/nsd_control-status.out b/tests/fixtures/generic/nsd_control-status.out
new file mode 100644
index 00000000..0a912231
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-status.out
@@ -0,0 +1,3 @@
+version: 4.6.2
+verbosity: 2
+ratelimit: 0
diff --git a/tests/fixtures/generic/nsd_control-tsig.json b/tests/fixtures/generic/nsd_control-tsig.json
new file mode 100644
index 00000000..a0bceb27
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-tsig.json
@@ -0,0 +1 @@
+[{"key":{"name":"test-tsig","secret":"83d61b962c20f5352955dc197d3db6d3","algorithm":"hmac-md5"}}]
diff --git a/tests/fixtures/generic/nsd_control-tsig.out b/tests/fixtures/generic/nsd_control-tsig.out
new file mode 100644
index 00000000..4e55eb1a
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-tsig.out
@@ -0,0 +1 @@
+key: name: "test-tsig" secret: "83d61b962c20f5352955dc197d3db6d3" algorithm: hmac-md5
diff --git a/tests/fixtures/generic/nsd_control-zonestatus.json b/tests/fixtures/generic/nsd_control-zonestatus.json
new file mode 100644
index 00000000..11008c72
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-zonestatus.json
@@ -0,0 +1 @@
+[{"zone":"sunet.se","status":{"state":"ok","served-serial":"2023091302 since 2023-09-14T00:50:11","commit-serial":"2023091302 since 2023-09-14T07:04:05","wait":"27023 sec between attempts"}}]
diff --git a/tests/fixtures/generic/nsd_control-zonestatus.out b/tests/fixtures/generic/nsd_control-zonestatus.out
new file mode 100644
index 00000000..a253dc7e
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control-zonestatus.out
@@ -0,0 +1,5 @@
+zone: sunet.se
+ state: ok
+ served-serial: "2023091302 since 2023-09-14T00:50:11"
+ commit-serial: "2023091302 since 2023-09-14T07:04:05"
+ wait: "27023 sec between attempts"
diff --git a/tests/fixtures/generic/nsd_control.json b/tests/fixtures/generic/nsd_control.json
new file mode 100644
index 00000000..c078b95b
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control.json
@@ -0,0 +1 @@
+[{"command":"ok"}]
diff --git a/tests/fixtures/generic/nsd_control.out b/tests/fixtures/generic/nsd_control.out
new file mode 100644
index 00000000..9766475a
--- /dev/null
+++ b/tests/fixtures/generic/nsd_control.out
@@ -0,0 +1 @@
+ok
diff --git a/tests/fixtures/generic/os-release-centos b/tests/fixtures/generic/os-release-centos
new file mode 100644
index 00000000..c276e3ae
--- /dev/null
+++ b/tests/fixtures/generic/os-release-centos
@@ -0,0 +1,15 @@
+NAME="CentOS Linux"
+VERSION="7 (Core)"
+ID="centos"
+ID_LIKE="rhel fedora"
+VERSION_ID="7"
+PRETTY_NAME="CentOS Linux 7 (Core)"
+ANSI_COLOR="0;31"
+CPE_NAME="cpe:/o:centos:centos:7"
+HOME_URL="https://www.centos.org/"
+BUG_REPORT_URL="https://bugs.centos.org/"
+
+CENTOS_MANTISBT_PROJECT="CentOS-7"
+CENTOS_MANTISBT_PROJECT_VERSION="7"
+REDHAT_SUPPORT_PRODUCT="centos"
+REDHAT_SUPPORT_PRODUCT_VERSION="7"
diff --git a/tests/fixtures/generic/os-release-centos.json b/tests/fixtures/generic/os-release-centos.json
new file mode 100644
index 00000000..dd17463d
--- /dev/null
+++ b/tests/fixtures/generic/os-release-centos.json
@@ -0,0 +1 @@
+{"NAME":"CentOS Linux","VERSION":"7 (Core)","ID":"centos","ID_LIKE":"rhel fedora","VERSION_ID":"7","PRETTY_NAME":"CentOS Linux 7 (Core)","ANSI_COLOR":"0;31","CPE_NAME":"cpe:/o:centos:centos:7","HOME_URL":"https://www.centos.org/","BUG_REPORT_URL":"https://bugs.centos.org/","CENTOS_MANTISBT_PROJECT":"CentOS-7","CENTOS_MANTISBT_PROJECT_VERSION":"7","REDHAT_SUPPORT_PRODUCT":"centos","REDHAT_SUPPORT_PRODUCT_VERSION":"7"}
diff --git a/tests/fixtures/generic/os-release-ubuntu b/tests/fixtures/generic/os-release-ubuntu
new file mode 100644
index 00000000..f1839e72
--- /dev/null
+++ b/tests/fixtures/generic/os-release-ubuntu
@@ -0,0 +1,12 @@
+NAME="Ubuntu"
+VERSION="18.04.5 LTS (Bionic Beaver)"
+ID=ubuntu
+ID_LIKE=debian
+PRETTY_NAME="Ubuntu 18.04.5 LTS"
+VERSION_ID="18.04"
+HOME_URL="https://www.ubuntu.com/"
+SUPPORT_URL="https://help.ubuntu.com/"
+BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
+PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
+VERSION_CODENAME=bionic
+UBUNTU_CODENAME=bionic
diff --git a/tests/fixtures/generic/os-release-ubuntu.json b/tests/fixtures/generic/os-release-ubuntu.json
new file mode 100644
index 00000000..86607162
--- /dev/null
+++ b/tests/fixtures/generic/os-release-ubuntu.json
@@ -0,0 +1 @@
+{"NAME":"Ubuntu","VERSION":"18.04.5 LTS (Bionic Beaver)","ID":"ubuntu","ID_LIKE":"debian","PRETTY_NAME":"Ubuntu 18.04.5 LTS","VERSION_ID":"18.04","HOME_URL":"https://www.ubuntu.com/","SUPPORT_URL":"https://help.ubuntu.com/","BUG_REPORT_URL":"https://bugs.launchpad.net/ubuntu/","PRIVACY_POLICY_URL":"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy","VERSION_CODENAME":"bionic","UBUNTU_CODENAME":"bionic"}
diff --git a/tests/fixtures/generic/pidstat-ht-streaming.json b/tests/fixtures/generic/pidstat-ht-streaming.json
new file mode 100644
index 00000000..57be15b3
--- /dev/null
+++ b/tests/fixtures/generic/pidstat-ht-streaming.json
@@ -0,0 +1 @@
+[{"time":1692579199,"uid":0,"pid":1,"percent_usr":0.0,"percent_system":0.07,"percent_guest":0.0,"percent_wait":0.08,"percent_cpu":0.08,"cpu":0,"command":"systemd"},{"time":1692579199,"uid":0,"pid":1,"usr_ms":2890,"system_ms":4260,"guest_ms":0,"command":"systemd"}]
diff --git a/tests/fixtures/generic/pidstat-ht.json b/tests/fixtures/generic/pidstat-ht.json
new file mode 100644
index 00000000..57be15b3
--- /dev/null
+++ b/tests/fixtures/generic/pidstat-ht.json
@@ -0,0 +1 @@
+[{"time":1692579199,"uid":0,"pid":1,"percent_usr":0.0,"percent_system":0.07,"percent_guest":0.0,"percent_wait":0.08,"percent_cpu":0.08,"cpu":0,"command":"systemd"},{"time":1692579199,"uid":0,"pid":1,"usr_ms":2890,"system_ms":4260,"guest_ms":0,"command":"systemd"}]
diff --git a/tests/fixtures/generic/pidstat-ht.out b/tests/fixtures/generic/pidstat-ht.out
new file mode 100644
index 00000000..b655c7de
--- /dev/null
+++ b/tests/fixtures/generic/pidstat-ht.out
@@ -0,0 +1,8 @@
+Linux 4.18.0-477.10.1.el8_8.x86_64 (localhost.localdomain) 08/20/2023 _x86_64_ (1 CPU)
+
+# Time UID PID %usr %system %guest %wait %CPU CPU Command
+1692579199 0 1 0.00 0.07 0.00 0.08 0.08 0 systemd
+
+# Time UID PID usr-ms system-ms guest-ms Command
+1692579199 0 1 2890 4260 0 systemd
+
diff --git a/tests/fixtures/generic/x509-cert-superfluous-bits.json b/tests/fixtures/generic/x509-cert-superfluous-bits.json
new file mode 100644
index 00000000..4bc5172d
--- /dev/null
+++ b/tests/fixtures/generic/x509-cert-superfluous-bits.json
@@ -0,0 +1 @@
+[{"tbs_certificate": {"version": "v3", "serial_number": "39:cc:ff:59:4d:25:68:30:24:0e:db:80:98:d1:94:e0:69:95:b7:49", "signature": {"algorithm": "sha256_rsa", "parameters": null}, "issuer": {"common_name": "cryptography.io"}, "validity": {"not_before": 1695218897, "not_after": 1697897297, "not_before_iso": "2023-09-20T14:08:17+00:00", "not_after_iso": "2023-10-21T14:08:17+00:00"}, "subject": {"common_name": "cryptography.io"}, "subject_public_key_info": {"algorithm": {"algorithm": "rsa", "parameters": null}, "public_key": {"modulus": "a3:cf:40:41:89:98:21:ad:22:e3:b3:fe:30:95:cf:b6:6b:f6:45:11:c5:6f:51:e3:51:01:a1:38:fc:f8:43:48:5b:ed:e2:8c:69:d0:e1:13:92:04:dd:08:c5:5f:bb:ab:fe:1c:20:d3:3b:18:cd:52:f2:cf:44:9e:c6:9d:60:e4:62:26:a6:cc:2b:27:85:58:1f:4e:2f:48:27:9a:6c:b3:7e:61:5d:c7:d8:e1:20:a4:22:4b:97:38:2f:53:97:ca:3d:3f:28:22:43:24:be:50:3f:07:e9:d4:ef:06:07:ea:9c:1c:58:32:4e:ec:5c:0f:fa:6d:72:6c:66:1e:40:a3:a5:ce:01:d1:08:a7:e0:15:82:27:2c:01:8e:26:a4:21:49:49:7f:05:44:8b:1c:ce:29:25:5e:ba:15:b1:9a:dc:0c:05:5d:82:b5:57:67:b3:34:f0:13:d0:59:59:b4:88:90:20:c2:ae:19:5d:4b:db:4b:59:b5:d8:32:34:0c:95:f1:3f:fe:25:54:47:59:02:b6:00:55:13:a0:ec:a9:7d:95:02:2a:9a:69:d4:a3:e7:3d:47:c4:b1:41:47:46:5d:44:c9:8e:b0:bb:68:00:1f:a3:0a:7f:93:99:c8:ef:b4:45:ea:3b:45:5f:3d:68:5b:41:ea:53:9b:1b:17:dc:41", "public_exponent": 65537}}, "issuer_unique_id": null, "subject_unique_id": null, "extensions": [{"extn_id": "key_usage", "critical": true, "extn_value": ["crl_sign", "data_encipherment", "decipher_only", "digital_signature", "encipher_only", "key_agreement", "key_cert_sign", "key_encipherment", "non_repudiation"]}], "serial_number_str": "329984069978047138672494938076577194533836928841"}, "signature_algorithm": {"algorithm": "sha256_rsa", "parameters": null}, "signature_value": "68:25:77:b8:cc:e2:d9:c0:38:18:16:d6:3f:b3:ea:1a:91:f9:6e:60:b8:d1:cc:88:b1:e1:3c:34:23:51:2d:68:31:bc:8a:f7:c5:23:03:d2:3c:e4:00:dc:23:fa:8b:9b:25:f2:63:32:37:d9:dc:8a:b0:7b:18:2f:19:95:33:be:15:9a:65:f9:ad:41:d7:08:08:d3:b5:c9:34:32:82:67:48:47:0b:6b:4a:42:20:8b:97:eb:dc:6a:0c:a6:00:9b:84:ac:0a:07:5e:49:19:4c:1a:63:74:18:c8:55:3c:50:38:47:76:fb:31:d6:a5:27:76:af:9d:f5:f9:9b:5e:5a:7c:5c:7f:6d:30:24:87:e4:3d:fe:2a:5a:77:43:58:c5:e2:85:ac:df:72:5c:4e:a4:ac:7c:e3:29:6a:cb:fc:5d:20:92:16:c6:91:67:77:6d:23:fb:05:0a:c9:c0:fd:c9:76:65:05:08:20:2a:2e:66:cf:67:6b:65:2a:a5:ba:b8:33:4a:32:e0:42:ef:1d:cc:e0:ec:f7:da:18:0e:77:a4:65:f5:cb:45:1e:8f:c6:3d:f0:70:42:50:9b:2a:86:d9:6b:6f:2d:60:d7:59:ae:ff:9b:f3:78:99:c8:d0:19:7a:7a:99:39:2c:91:1c:63:00:5a:60:f4:20:af:c0:b6:39"}]
\ No newline at end of file
diff --git a/tests/fixtures/generic/x509-cert-superfluous-bits.pem b/tests/fixtures/generic/x509-cert-superfluous-bits.pem
new file mode 100644
index 00000000..c4d9ef03
--- /dev/null
+++ b/tests/fixtures/generic/x509-cert-superfluous-bits.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAb2gAwIBAgIUOcz/WU0laDAkDtuAmNGU4GmVt0kwDQYJKoZIhvcNAQEL
+BQAwGjEYMBYGA1UEAwwPY3J5cHRvZ3JhcGh5LmlvMB4XDTIzMDkyMDE0MDgxN1oX
+DTIzMTAyMTE0MDgxN1owGjEYMBYGA1UEAwwPY3J5cHRvZ3JhcGh5LmlvMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo89AQYmYIa0i47P+MJXPtmv2RRHF
+b1HjUQGhOPz4Q0hb7eKMadDhE5IE3QjFX7ur/hwg0zsYzVLyz0Sexp1g5GImpswr
+J4VYH04vSCeabLN+YV3H2OEgpCJLlzgvU5fKPT8oIkMkvlA/B+nU7wYH6pwcWDJO
+7FwP+m1ybGYeQKOlzgHRCKfgFYInLAGOJqQhSUl/BUSLHM4pJV66FbGa3AwFXYK1
+V2ezNPAT0FlZtIiQIMKuGV1L20tZtdgyNAyV8T/+JVRHWQK2AFUToOypfZUCKppp
+1KPnPUfEsUFHRl1EyY6wu2gAH6MKf5OZyO+0Reo7RV89aFtB6lObGxfcQQIDAQAB
+oxMwETAPBgNVHQ8BAf8EBQMDAP//MA0GCSqGSIb3DQEBCwUAA4IBAQBoJXe4zOLZ
+wDgYFtY/s+oakfluYLjRzIix4Tw0I1EtaDG8ivfFIwPSPOQA3CP6i5sl8mMyN9nc
+irB7GC8ZlTO+FZpl+a1B1wgI07XJNDKCZ0hHC2tKQiCLl+vcagymAJuErAoHXkkZ
+TBpjdBjIVTxQOEd2+zHWpSd2r531+ZteWnxcf20wJIfkPf4qWndDWMXihazfclxO
+pKx84ylqy/xdIJIWxpFnd20j+wUKycD9yXZlBQggKi5mz2drZSqlurgzSjLgQu8d
+zODs99oYDnekZfXLRR6Pxj3wcEJQmyqG2WtvLWDXWa7/m/N4mcjQGXp6mTkskRxj
+AFpg9CCvwLY5
+-----END CERTIFICATE-----
diff --git a/tests/fixtures/generic/x509-negative-serial.json b/tests/fixtures/generic/x509-negative-serial.json
new file mode 100644
index 00000000..a9e87bb7
--- /dev/null
+++ b/tests/fixtures/generic/x509-negative-serial.json
@@ -0,0 +1 @@
+[{"tbs_certificate": {"version": "v3", "serial_number": "(Negative)43:21:98:76:dc:ba:00:00:43:21:98:76:dc:ba:00:00:11:11:00:00", "signature": {"algorithm": "sha512_rsa", "parameters": null}, "issuer": {"country_name": "DE", "state_or_province_name": "stateOrProvinceName", "locality_name": "localityName", "organization_name": "organizationName", "organizational_unit_name": "organizationUnitName", "common_name": "commonName", "email_address": "emailAddress"}, "validity": {"not_before": 1693312810, "not_after": 2008672810, "not_before_iso": "2023-08-29T12:40:10+00:00", "not_after_iso": "2033-08-26T12:40:10+00:00"}, "subject": {"country_name": "DE", "state_or_province_name": "stateOrProvinceName", "locality_name": "localityName", "organization_name": "organizationName", "organizational_unit_name": "organizationUnitName", "common_name": "commonName", "email_address": "emailAddress"}, "subject_public_key_info": {"algorithm": {"algorithm": "rsa", "parameters": null}, "public_key": {"modulus": "a8:fe:f8:79:c6:bb:9e:0a:da:e1:ac:ae:5b:2b:b1:24:69:92:ec:c7:e5:af:8a:30:a9:89:f9:38:a7:93:c9:ca:74:2e:cb:91:a4:67:ea:8d:74:78:17:3b:7b:4e:18:08:dc:26:7e:8c:92:a2:47:86:28:3e:5b:43:e8:5c:1d:39:2f:90:7a:18:1e:da:ec:1a:00:bf:7e:86:b8:ab:fd:92:e0:79:eb:9e:8d:09:c5:36:ea:2d:15:9a:3e:d7:a6:8d:99:a8:96:41:fb:c0:9f:4f:37:0e:ac:9d:af:61:c0:53:63:f5:6a:45:b5:ef:a1:cd:f3:58:1d:4d:b5:9c:7b:f5", "public_exponent": 65537}}, "issuer_unique_id": null, "subject_unique_id": null, "extensions": null, "serial_number_str": "-383251587750925609224665374206538004257901182976"}, "signature_algorithm": {"algorithm": "sha512_rsa", "parameters": null}, "signature_value": "72:0c:3f:d9:b2:22:1c:57:1b:d6:b6:89:5a:e4:1b:55:5e:12:b2:d8:6d:c4:d8:f8:d3:2e:3e:02:18:2a:b3:7e:2c:8a:b6:4c:da:c5:f2:b8:25:5d:68:64:ca:66:be:6a:30:4a:60:bc:87:d8:05:82:82:cd:64:41:ad:03:ed:d7:38:e2:ac:19:07:83:40:26:a2:81:23:6a:6d:23:13:74:8d:f4:23:40:40:ab:d9:bd:1f:91:17:44:6e:58:7a:ba:b9:3f:3e:06:c7:00:7c:46:46:d9:d4:78:06:8f:7b:8a:4a:ff:72:71:da:06:21:6a:b7:8c:cd:cf:0e:cd:bc:e3"}]
\ No newline at end of file
diff --git a/tests/fixtures/generic/x509-negative-serial.pem b/tests/fixtures/generic/x509-negative-serial.pem
new file mode 100644
index 00000000..29abf801
--- /dev/null
+++ b/tests/fixtures/generic/x509-negative-serial.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC5TCCAk6gAwIBAgIUvN5niSNF//+83meJI0X//+7vAAAwDQYJKoZIhvcNAQEN
+BQAwga4xCzAJBgNVBAYTAkRFMRwwGgYDVQQIDBNzdGF0ZU9yUHJvdmluY2VOYW1l
+MRUwEwYDVQQHDAxsb2NhbGl0eU5hbWUxGTAXBgNVBAoMEG9yZ2FuaXphdGlvbk5h
+bWUxHTAbBgNVBAsMFG9yZ2FuaXphdGlvblVuaXROYW1lMRMwEQYDVQQDDApjb21t
+b25OYW1lMRswGQYJKoZIhvcNAQkBFgxlbWFpbEFkZHJlc3MwHhcNMjMwODI5MTI0
+MDEwWhcNMzMwODI2MTI0MDEwWjCBrjELMAkGA1UEBhMCREUxHDAaBgNVBAgME3N0
+YXRlT3JQcm92aW5jZU5hbWUxFTATBgNVBAcMDGxvY2FsaXR5TmFtZTEZMBcGA1UE
+CgwQb3JnYW5pemF0aW9uTmFtZTEdMBsGA1UECwwUb3JnYW5pemF0aW9uVW5pdE5h
+bWUxEzARBgNVBAMMCmNvbW1vbk5hbWUxGzAZBgkqhkiG9w0BCQEWDGVtYWlsQWRk
+cmVzczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqP74eca7ngra4ayuWyux
+JGmS7Mflr4owqYn5OKeTycp0LsuRpGfqjXR4Fzt7ThgI3CZ+jJKiR4YoPltD6Fwd
+OS+Qehge2uwaAL9+hrir/ZLgeeuejQnFNuotFZo+16aNmaiWQfvAn083Dqydr2HA
+U2P1akW176HN81gdTbWce/UCAwEAATANBgkqhkiG9w0BAQ0FAAOBgQByDD/ZsiIc
+VxvWtola5BtVXhKy2G3E2PjTLj4CGCqzfiyKtkzaxfK4JV1oZMpmvmowSmC8h9gF
+goLNZEGtA+3XOOKsGQeDQCaigSNqbSMTdI30I0BAq9m9H5EXRG5Yerq5Pz4GxwB8
+RkbZ1HgGj3uKSv9ycdoGIWq3jM3PDs284w==
+-----END CERTIFICATE-----
diff --git a/tests/fixtures/generic/xml-nmap-raw.json b/tests/fixtures/generic/xml-nmap-raw.json
index accbe22f..0ab9f247 100644
--- a/tests/fixtures/generic/xml-nmap-raw.json
+++ b/tests/fixtures/generic/xml-nmap-raw.json
@@ -1 +1 @@
-{"nmaprun":{"_scanner":"nmap","_args":"nmap -oX - -p 443 galaxy.ansible.com","_start":"1666781498","_startstr":"Wed Oct 26 11:51:38 2022","_version":"7.92","_xmloutputversion":"1.05","scaninfo":{"_type":"connect","_protocol":"tcp","_numservices":"1","_services":"443"},"verbose":{"_level":"0"},"debugging":{"_level":"0"},"hosthint":{"status":{"_state":"up","_reason":"unknown-response","_reason_ttl":"0"},"address":{"_addr":"172.67.68.251","_addrtype":"ipv4"},"hostnames":{"hostname":{"_name":"galaxy.ansible.com","_type":"user"}}},"host":{"_starttime":"1666781498","_endtime":"1666781498","status":{"_state":"up","_reason":"syn-ack","_reason_ttl":"0"},"address":{"_addr":"172.67.68.251","_addrtype":"ipv4"},"hostnames":{"hostname":[{"_name":"galaxy.ansible.com","_type":"user"},{"_name":"galaxy.ansible.com","_type":"PTR"}]},"ports":{"port":{"_protocol":"tcp","_portid":"443","state":{"_state":"open","_reason":"syn-ack","_reason_ttl":"0"},"service":{"_name":"https","_method":"table","_conf":"3"}}},"times":{"_srtt":"12260","_rttvar":"9678","_to":"100000"}},"runstats":{"finished":{"_time":"1666781498","_timestr":"Wed Oct 26 11:51:38 2022","_summary":"Nmap done at Wed Oct 26 11:51:38 2022; 1 IP address (1 host up) scanned in 0.10 seconds","_elapsed":"0.10","_exit":"success"},"hosts":{"_up":"1","_down":"0","_total":"1"}}}}
+{"#comment":"Nmap 7.92 scan initiated Wed Oct 26 11:51:38 2022 as: nmap -oX - -p 443 galaxy.ansible.com","nmaprun":{"_scanner":"nmap","_args":"nmap -oX - -p 443 galaxy.ansible.com","_start":"1666781498","_startstr":"Wed Oct 26 11:51:38 2022","_version":"7.92","_xmloutputversion":"1.05","scaninfo":{"_type":"connect","_protocol":"tcp","_numservices":"1","_services":"443"},"verbose":{"_level":"0"},"debugging":{"_level":"0"},"hosthint":{"status":{"_state":"up","_reason":"unknown-response","_reason_ttl":"0"},"address":{"_addr":"172.67.68.251","_addrtype":"ipv4"},"hostnames":{"hostname":{"_name":"galaxy.ansible.com","_type":"user"}}},"host":{"_starttime":"1666781498","_endtime":"1666781498","status":{"_state":"up","_reason":"syn-ack","_reason_ttl":"0"},"address":{"_addr":"172.67.68.251","_addrtype":"ipv4"},"hostnames":{"hostname":[{"_name":"galaxy.ansible.com","_type":"user"},{"_name":"galaxy.ansible.com","_type":"PTR"}]},"ports":{"port":{"_protocol":"tcp","_portid":"443","state":{"_state":"open","_reason":"syn-ack","_reason_ttl":"0"},"service":{"_name":"https","_method":"table","_conf":"3"}}},"times":{"_srtt":"12260","_rttvar":"9678","_to":"100000"}},"runstats":{"finished":{"_time":"1666781498","_timestr":"Wed Oct 26 11:51:38 2022","_summary":"Nmap done at Wed Oct 26 11:51:38 2022; 1 IP address (1 host up) scanned in 0.10 seconds","_elapsed":"0.10","_exit":"success"},"hosts":{"_up":"1","_down":"0","_total":"1"}}}}
diff --git a/tests/fixtures/generic/xml-nmap.json b/tests/fixtures/generic/xml-nmap.json
index 849ea04a..7423a905 100644
--- a/tests/fixtures/generic/xml-nmap.json
+++ b/tests/fixtures/generic/xml-nmap.json
@@ -1 +1 @@
-{"nmaprun":{"@scanner":"nmap","@args":"nmap -oX - -p 443 galaxy.ansible.com","@start":"1666781498","@startstr":"Wed Oct 26 11:51:38 2022","@version":"7.92","@xmloutputversion":"1.05","scaninfo":{"@type":"connect","@protocol":"tcp","@numservices":"1","@services":"443"},"verbose":{"@level":"0"},"debugging":{"@level":"0"},"hosthint":{"status":{"@state":"up","@reason":"unknown-response","@reason_ttl":"0"},"address":{"@addr":"172.67.68.251","@addrtype":"ipv4"},"hostnames":{"hostname":{"@name":"galaxy.ansible.com","@type":"user"}}},"host":{"@starttime":"1666781498","@endtime":"1666781498","status":{"@state":"up","@reason":"syn-ack","@reason_ttl":"0"},"address":{"@addr":"172.67.68.251","@addrtype":"ipv4"},"hostnames":{"hostname":[{"@name":"galaxy.ansible.com","@type":"user"},{"@name":"galaxy.ansible.com","@type":"PTR"}]},"ports":{"port":{"@protocol":"tcp","@portid":"443","state":{"@state":"open","@reason":"syn-ack","@reason_ttl":"0"},"service":{"@name":"https","@method":"table","@conf":"3"}}},"times":{"@srtt":"12260","@rttvar":"9678","@to":"100000"}},"runstats":{"finished":{"@time":"1666781498","@timestr":"Wed Oct 26 11:51:38 2022","@summary":"Nmap done at Wed Oct 26 11:51:38 2022; 1 IP address (1 host up) scanned in 0.10 seconds","@elapsed":"0.10","@exit":"success"},"hosts":{"@up":"1","@down":"0","@total":"1"}}}}
+{"#comment":"Nmap 7.92 scan initiated Wed Oct 26 11:51:38 2022 as: nmap -oX - -p 443 galaxy.ansible.com","nmaprun":{"@scanner":"nmap","@args":"nmap -oX - -p 443 galaxy.ansible.com","@start":"1666781498","@startstr":"Wed Oct 26 11:51:38 2022","@version":"7.92","@xmloutputversion":"1.05","scaninfo":{"@type":"connect","@protocol":"tcp","@numservices":"1","@services":"443"},"verbose":{"@level":"0"},"debugging":{"@level":"0"},"hosthint":{"status":{"@state":"up","@reason":"unknown-response","@reason_ttl":"0"},"address":{"@addr":"172.67.68.251","@addrtype":"ipv4"},"hostnames":{"hostname":{"@name":"galaxy.ansible.com","@type":"user"}}},"host":{"@starttime":"1666781498","@endtime":"1666781498","status":{"@state":"up","@reason":"syn-ack","@reason_ttl":"0"},"address":{"@addr":"172.67.68.251","@addrtype":"ipv4"},"hostnames":{"hostname":[{"@name":"galaxy.ansible.com","@type":"user"},{"@name":"galaxy.ansible.com","@type":"PTR"}]},"ports":{"port":{"@protocol":"tcp","@portid":"443","state":{"@state":"open","@reason":"syn-ack","@reason_ttl":"0"},"service":{"@name":"https","@method":"table","@conf":"3"}}},"times":{"@srtt":"12260","@rttvar":"9678","@to":"100000"}},"runstats":{"finished":{"@time":"1666781498","@timestr":"Wed Oct 26 11:51:38 2022","@summary":"Nmap done at Wed Oct 26 11:51:38 2022; 1 IP address (1 host up) scanned in 0.10 seconds","@elapsed":"0.10","@exit":"success"},"hosts":{"@up":"1","@down":"0","@total":"1"}}}}
diff --git a/tests/fixtures/generic/xrandr_3.out b/tests/fixtures/generic/xrandr_3.out
new file mode 100644
index 00000000..8eaf62f0
--- /dev/null
+++ b/tests/fixtures/generic/xrandr_3.out
@@ -0,0 +1,8 @@
+Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384
+test-3-1 disconnected primary (normal left inverted right x axis y axis)
+test-3-2 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 521mm x 293mm
+ 1920x1080 60.00*+ 59.94 60.00
+ 1680x1050 60.00 59.88
+ 1400x1050 60.00
+ 1600x900 60.00
+ 1280x1024 75.02 60.02 60.00
diff --git a/tests/fixtures/generic/xrandr_fix_spaces.json b/tests/fixtures/generic/xrandr_fix_spaces.json
deleted file mode 100644
index aac9c63a..00000000
--- a/tests/fixtures/generic/xrandr_fix_spaces.json
+++ /dev/null
@@ -1 +0,0 @@
-{"screens":[{"screen_number":0,"minimum_width":320,"minimum_height":200,"current_width":2806,"current_height":900,"maximum_width":8192,"maximum_height":8192,"associated_device":{"associated_modes":[{"resolution_width":1366,"resolution_height":768,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":true,"is_preferred":true}]},{"resolution_width":1280,"resolution_height":720,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false},{"frequency":59.99,"is_current":false,"is_preferred":false},{"frequency":59.86,"is_current":false,"is_preferred":false},{"frequency":59.74,"is_current":false,"is_preferred":false}]},{"resolution_width":1024,"resolution_height":768,"is_high_resolution":false,"frequencies":[{"frequency":60.04,"is_current":false,"is_preferred":false},{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":960,"resolution_height":720,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":928,"resolution_height":696,"is_high_resolution":false,"frequencies":[{"frequency":60.05,"is_current":false,"is_preferred":false}]},{"resolution_width":896,"resolution_height":672,"is_high_resolution":false,"frequencies":[{"frequency":60.01,"is_current":false,"is_preferred":false}]},{"resolution_width":1024,"resolution_height":576,"is_high_resolution":false,"frequencies":[{"frequency":59.95,"is_current":false,"is_preferred":false},{"frequency":59.96,"is_current":false,"is_preferred":false},{"frequency":59.9,"is_current":false,"is_preferred":false},{"frequency":59.82,"is_current":false,"is_preferred":false}]},{"resolution_width":960,"resolution_height":600,"is_high_resolution":false,"frequencies":[{"frequency":59.93,"is_current":false,"is_preferred":false},{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":960,"resolution_height":540,"is_high_resolution":false,"frequencies":[{"frequency":59.96,"is_current":false,"is_preferred":false},{"frequency":59.99,"is_current":false,"is_preferred":false},{"frequency":59.63,"is_current":false,"is_preferred":false},{"frequency":59.82,"is_current":false,"is_preferred":false}]},{"resolution_width":800,"resolution_height":600,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false},{"frequency":60.32,"is_current":false,"is_preferred":false},{"frequency":56.25,"is_current":false,"is_preferred":false}]},{"resolution_width":840,"resolution_height":525,"is_high_resolution":false,"frequencies":[{"frequency":60.01,"is_current":false,"is_preferred":false},{"frequency":59.88,"is_current":false,"is_preferred":false}]},{"resolution_width":864,"resolution_height":486,"is_high_resolution":false,"frequencies":[{"frequency":59.92,"is_current":false,"is_preferred":false},{"frequency":59.57,"is_current":false,"is_preferred":false}]},{"resolution_width":700,"resolution_height":525,"is_high_resolution":false,"frequencies":[{"frequency":59.98,"is_current":false,"is_preferred":false}]},{"resolution_width":800,"resolution_height":450,"is_high_resolution":false,"frequencies":[{"frequency":59.95,"is_current":false,"is_preferred":false},{"frequency":59.82,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":512,"is_high_resolution":false,"frequencies":[{"frequency":60.02,"is_current":false,"is_preferred":false}]},{"resolution_width":700,"resolution_height":450,"is_high_resolution":false,"frequencies":[{"frequency":59.96,"is_current":false,"is_preferred":false},{"frequency":59.88,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":480,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false},{"frequency":59.94,"is_current":false,"is_preferred":false}]},{"resolution_width":720,"resolution_height":405,"is_high_resolution":false,"frequencies":[{"frequency":59.51,"is_current":false,"is_preferred":false},{"frequency":58.99,"is_current":false,"is_preferred":false}]},{"resolution_width":684,"resolution_height":384,"is_high_resolution":false,"frequencies":[{"frequency":59.88,"is_current":false,"is_preferred":false},{"frequency":59.85,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":400,"is_high_resolution":false,"frequencies":[{"frequency":59.88,"is_current":false,"is_preferred":false},{"frequency":59.98,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":360,"is_high_resolution":false,"frequencies":[{"frequency":59.86,"is_current":false,"is_preferred":false},{"frequency":59.83,"is_current":false,"is_preferred":false},{"frequency":59.84,"is_current":false,"is_preferred":false},{"frequency":59.32,"is_current":false,"is_preferred":false}]},{"resolution_width":512,"resolution_height":384,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":512,"resolution_height":288,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false},{"frequency":59.92,"is_current":false,"is_preferred":false}]},{"resolution_width":480,"resolution_height":270,"is_high_resolution":false,"frequencies":[{"frequency":59.63,"is_current":false,"is_preferred":false},{"frequency":59.82,"is_current":false,"is_preferred":false}]},{"resolution_width":400,"resolution_height":300,"is_high_resolution":false,"frequencies":[{"frequency":60.32,"is_current":false,"is_preferred":false},{"frequency":56.34,"is_current":false,"is_preferred":false}]},{"resolution_width":432,"resolution_height":243,"is_high_resolution":false,"frequencies":[{"frequency":59.92,"is_current":false,"is_preferred":false},{"frequency":59.57,"is_current":false,"is_preferred":false}]},{"resolution_width":320,"resolution_height":240,"is_high_resolution":false,"frequencies":[{"frequency":60.05,"is_current":false,"is_preferred":false}]},{"resolution_width":360,"resolution_height":202,"is_high_resolution":false,"frequencies":[{"frequency":59.51,"is_current":false,"is_preferred":false},{"frequency":59.13,"is_current":false,"is_preferred":false}]},{"resolution_width":320,"resolution_height":180,"is_high_resolution":false,"frequencies":[{"frequency":59.84,"is_current":false,"is_preferred":false},{"frequency":59.32,"is_current":false,"is_preferred":false}]}],"is_connected":true,"is_primary":true,"device_name":"LVDS-1","rotation":"normal","reflection":"normal","resolution_width":1366,"resolution_height":768,"offset_width":0,"offset_height":0,"dimension_width":344,"dimension_height":194}}],"unassociated_devices":[{"associated_modes":[{"resolution_width":1440,"resolution_height":900,"is_high_resolution":false,"frequencies":[{"frequency":59.89,"is_current":true,"is_preferred":true},{"frequency":74.98,"is_current":false,"is_preferred":false}]},{"resolution_width":1280,"resolution_height":1024,"is_high_resolution":false,"frequencies":[{"frequency":75.02,"is_current":false,"is_preferred":false},{"frequency":60.02,"is_current":false,"is_preferred":false}]},{"resolution_width":1280,"resolution_height":960,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":1280,"resolution_height":800,"is_high_resolution":false,"frequencies":[{"frequency":74.93,"is_current":false,"is_preferred":false},{"frequency":59.81,"is_current":false,"is_preferred":false}]},{"resolution_width":1152,"resolution_height":864,"is_high_resolution":false,"frequencies":[{"frequency":75.0,"is_current":false,"is_preferred":false}]},{"resolution_width":1024,"resolution_height":768,"is_high_resolution":false,"frequencies":[{"frequency":75.03,"is_current":false,"is_preferred":false},{"frequency":70.07,"is_current":false,"is_preferred":false},{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":832,"resolution_height":624,"is_high_resolution":false,"frequencies":[{"frequency":74.55,"is_current":false,"is_preferred":false}]},{"resolution_width":800,"resolution_height":600,"is_high_resolution":false,"frequencies":[{"frequency":72.19,"is_current":false,"is_preferred":false},{"frequency":75.0,"is_current":false,"is_preferred":false},{"frequency":60.32,"is_current":false,"is_preferred":false},{"frequency":56.25,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":480,"is_high_resolution":false,"frequencies":[{"frequency":75.0,"is_current":false,"is_preferred":false},{"frequency":72.81,"is_current":false,"is_preferred":false},{"frequency":66.67,"is_current":false,"is_preferred":false},{"frequency":59.94,"is_current":false,"is_preferred":false}]},{"resolution_width":720,"resolution_height":400,"is_high_resolution":false,"frequencies":[{"frequency":70.08,"is_current":false,"is_preferred":false}]}],"is_connected":true,"is_primary":false,"device_name":"VGA-1","rotation":"normal","reflection":"Y axis","resolution_width":1440,"resolution_height":900,"offset_width":1366,"offset_height":0,"dimension_width":408,"dimension_height":255},{"associated_modes":[],"is_connected":false,"is_primary":false,"device_name":"HDMI-1","rotation":"normal","reflection":"normal"},{"associated_modes":[],"is_connected":false,"is_primary":false,"device_name":"DP-1","rotation":"normal","reflection":"normal"}]}
diff --git a/tests/fixtures/generic/xrandr_fix_spaces.out b/tests/fixtures/generic/xrandr_fix_spaces.out
deleted file mode 100644
index f45bb098..00000000
--- a/tests/fixtures/generic/xrandr_fix_spaces.out
+++ /dev/null
@@ -1,44 +0,0 @@
-Screen 0: minimum 320 x 200, current 2806 x 900, maximum 8192 x 8192
-LVDS-1 connected primary 1366x768+0+0 (normal left inverted right x axis y axis) 344mm x 194mm
- 1366x768 60.00*+
- 1280x720 60.00 59.99 59.86 59.74
- 1024x768 60.04 60.00
- 960x720 60.00
- 928x696 60.05
- 896x672 60.01
- 1024x576 59.95 59.96 59.90 59.82
- 960x600 59.93 60.00
- 960x540 59.96 59.99 59.63 59.82
- 800x600 60.00 60.32 56.25
- 840x525 60.01 59.88
- 864x486 59.92 59.57
- 700x525 59.98
- 800x450 59.95 59.82
- 640x512 60.02
- 700x450 59.96 59.88
- 640x480 60.00 59.94
- 720x405 59.51 58.99
- 684x384 59.88 59.85
- 640x400 59.88 59.98
- 640x360 59.86 59.83 59.84 59.32
- 512x384 60.00
- 512x288 60.00 59.92
- 480x270 59.63 59.82
- 400x300 60.32 56.34
- 432x243 59.92 59.57
- 320x240 60.05
- 360x202 59.51 59.13
- 320x180 59.84 59.32
-VGA-1 connected 1440x900+1366+0 normal Y axis (normal left inverted right x axis y axis) 408mm x 255mm
- 1440x900 59.89*+ 74.98
- 1280x1024 75.02 60.02
- 1280x960 60.00
- 1280x800 74.93 59.81
- 1152x864 75.00
- 1024x768 75.03 70.07 60.00
- 832x624 74.55
- 800x600 72.19 75.00 60.32 56.25
- 640x480 75.00 72.81 66.67 59.94
- 720x400 70.08
-HDMI-1 disconnected (normal left inverted right x axis y axis)
-DP-1 disconnected (normal left inverted right x axis y axis)
diff --git a/tests/fixtures/generic/xrandr_is_current_fix.json b/tests/fixtures/generic/xrandr_is_current_fix.json
deleted file mode 100644
index 98ee6634..00000000
--- a/tests/fixtures/generic/xrandr_is_current_fix.json
+++ /dev/null
@@ -1 +0,0 @@
-{"screens":[{"screen_number":0,"minimum_width":320,"minimum_height":200,"current_width":1846,"current_height":768,"maximum_width":8192,"maximum_height":8192,"associated_device":{"associated_modes":[{"resolution_width":1366,"resolution_height":768,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":true,"is_preferred":true}]},{"resolution_width":1280,"resolution_height":720,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false},{"frequency":59.99,"is_current":false,"is_preferred":false},{"frequency":59.86,"is_current":false,"is_preferred":false},{"frequency":59.74,"is_current":false,"is_preferred":false}]},{"resolution_width":1024,"resolution_height":768,"is_high_resolution":false,"frequencies":[{"frequency":60.04,"is_current":false,"is_preferred":false},{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":960,"resolution_height":720,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":928,"resolution_height":696,"is_high_resolution":false,"frequencies":[{"frequency":60.05,"is_current":false,"is_preferred":false}]},{"resolution_width":896,"resolution_height":672,"is_high_resolution":false,"frequencies":[{"frequency":60.01,"is_current":false,"is_preferred":false}]},{"resolution_width":1024,"resolution_height":576,"is_high_resolution":false,"frequencies":[{"frequency":59.95,"is_current":false,"is_preferred":false},{"frequency":59.96,"is_current":false,"is_preferred":false},{"frequency":59.9,"is_current":false,"is_preferred":false},{"frequency":59.82,"is_current":false,"is_preferred":false}]},{"resolution_width":960,"resolution_height":600,"is_high_resolution":false,"frequencies":[{"frequency":59.93,"is_current":false,"is_preferred":false},{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":960,"resolution_height":540,"is_high_resolution":false,"frequencies":[{"frequency":59.96,"is_current":false,"is_preferred":false},{"frequency":59.99,"is_current":false,"is_preferred":false},{"frequency":59.63,"is_current":false,"is_preferred":false},{"frequency":59.82,"is_current":false,"is_preferred":false}]},{"resolution_width":800,"resolution_height":600,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false},{"frequency":60.32,"is_current":false,"is_preferred":false},{"frequency":56.25,"is_current":false,"is_preferred":false}]},{"resolution_width":840,"resolution_height":525,"is_high_resolution":false,"frequencies":[{"frequency":60.01,"is_current":false,"is_preferred":false},{"frequency":59.88,"is_current":false,"is_preferred":false}]},{"resolution_width":864,"resolution_height":486,"is_high_resolution":false,"frequencies":[{"frequency":59.92,"is_current":false,"is_preferred":false},{"frequency":59.57,"is_current":false,"is_preferred":false}]},{"resolution_width":700,"resolution_height":525,"is_high_resolution":false,"frequencies":[{"frequency":59.98,"is_current":false,"is_preferred":false}]},{"resolution_width":800,"resolution_height":450,"is_high_resolution":false,"frequencies":[{"frequency":59.95,"is_current":false,"is_preferred":false},{"frequency":59.82,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":512,"is_high_resolution":false,"frequencies":[{"frequency":60.02,"is_current":false,"is_preferred":false}]},{"resolution_width":700,"resolution_height":450,"is_high_resolution":false,"frequencies":[{"frequency":59.96,"is_current":false,"is_preferred":false},{"frequency":59.88,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":480,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false},{"frequency":59.94,"is_current":false,"is_preferred":false}]},{"resolution_width":720,"resolution_height":405,"is_high_resolution":false,"frequencies":[{"frequency":59.51,"is_current":false,"is_preferred":false},{"frequency":58.99,"is_current":false,"is_preferred":false}]},{"resolution_width":684,"resolution_height":384,"is_high_resolution":false,"frequencies":[{"frequency":59.88,"is_current":false,"is_preferred":false},{"frequency":59.85,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":400,"is_high_resolution":false,"frequencies":[{"frequency":59.88,"is_current":false,"is_preferred":false},{"frequency":59.98,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":360,"is_high_resolution":false,"frequencies":[{"frequency":59.86,"is_current":false,"is_preferred":false},{"frequency":59.83,"is_current":false,"is_preferred":false},{"frequency":59.84,"is_current":false,"is_preferred":false},{"frequency":59.32,"is_current":false,"is_preferred":false}]},{"resolution_width":512,"resolution_height":384,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":512,"resolution_height":288,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false},{"frequency":59.92,"is_current":false,"is_preferred":false}]},{"resolution_width":480,"resolution_height":270,"is_high_resolution":false,"frequencies":[{"frequency":59.63,"is_current":false,"is_preferred":false},{"frequency":59.82,"is_current":false,"is_preferred":false}]},{"resolution_width":400,"resolution_height":300,"is_high_resolution":false,"frequencies":[{"frequency":60.32,"is_current":false,"is_preferred":false},{"frequency":56.34,"is_current":false,"is_preferred":false}]},{"resolution_width":432,"resolution_height":243,"is_high_resolution":false,"frequencies":[{"frequency":59.92,"is_current":false,"is_preferred":false},{"frequency":59.57,"is_current":false,"is_preferred":false}]},{"resolution_width":320,"resolution_height":240,"is_high_resolution":false,"frequencies":[{"frequency":60.05,"is_current":false,"is_preferred":false}]},{"resolution_width":360,"resolution_height":202,"is_high_resolution":false,"frequencies":[{"frequency":59.51,"is_current":false,"is_preferred":false},{"frequency":59.13,"is_current":false,"is_preferred":false}]},{"resolution_width":320,"resolution_height":180,"is_high_resolution":false,"frequencies":[{"frequency":59.84,"is_current":false,"is_preferred":false},{"frequency":59.32,"is_current":false,"is_preferred":false}]}],"is_connected":true,"is_primary":true,"device_name":"LVDS-1","rotation":"normal","reflection":"normal","resolution_width":1366,"resolution_height":768,"offset_width":0,"offset_height":0,"dimension_width":344,"dimension_height":194}}],"unassociated_devices":[{"associated_modes":[{"resolution_width":1440,"resolution_height":900,"is_high_resolution":false,"frequencies":[{"frequency":59.89,"is_current":false,"is_preferred":true},{"frequency":74.98,"is_current":false,"is_preferred":false}]},{"resolution_width":1280,"resolution_height":1024,"is_high_resolution":false,"frequencies":[{"frequency":75.02,"is_current":false,"is_preferred":false},{"frequency":60.02,"is_current":false,"is_preferred":false}]},{"resolution_width":1280,"resolution_height":960,"is_high_resolution":false,"frequencies":[{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":1280,"resolution_height":800,"is_high_resolution":false,"frequencies":[{"frequency":74.93,"is_current":false,"is_preferred":false},{"frequency":59.81,"is_current":false,"is_preferred":false}]},{"resolution_width":1152,"resolution_height":864,"is_high_resolution":false,"frequencies":[{"frequency":75.0,"is_current":false,"is_preferred":false}]},{"resolution_width":1024,"resolution_height":768,"is_high_resolution":false,"frequencies":[{"frequency":75.03,"is_current":false,"is_preferred":false},{"frequency":70.07,"is_current":false,"is_preferred":false},{"frequency":60.0,"is_current":false,"is_preferred":false}]},{"resolution_width":832,"resolution_height":624,"is_high_resolution":false,"frequencies":[{"frequency":74.55,"is_current":false,"is_preferred":false}]},{"resolution_width":800,"resolution_height":600,"is_high_resolution":false,"frequencies":[{"frequency":72.19,"is_current":false,"is_preferred":false},{"frequency":75.0,"is_current":false,"is_preferred":false},{"frequency":60.32,"is_current":false,"is_preferred":false},{"frequency":56.25,"is_current":false,"is_preferred":false}]},{"resolution_width":640,"resolution_height":480,"is_high_resolution":false,"frequencies":[{"frequency":75.0,"is_current":true,"is_preferred":false},{"frequency":72.81,"is_current":false,"is_preferred":false},{"frequency":66.67,"is_current":false,"is_preferred":false},{"frequency":59.94,"is_current":false,"is_preferred":false}]},{"resolution_width":720,"resolution_height":400,"is_high_resolution":false,"frequencies":[{"frequency":70.08,"is_current":false,"is_preferred":false}]}],"is_connected":true,"is_primary":false,"device_name":"VGA-1","rotation":"left","reflection":"normal","resolution_width":480,"resolution_height":640,"offset_width":1366,"offset_height":0,"dimension_width":408,"dimension_height":255},{"associated_modes":[],"is_connected":false,"is_primary":false,"device_name":"HDMI-1","rotation":"normal","reflection":"normal"},{"associated_modes":[],"is_connected":false,"is_primary":false,"device_name":"DP-1","rotation":"normal","reflection":"normal"}]}
diff --git a/tests/fixtures/generic/xrandr_is_current_fix.out b/tests/fixtures/generic/xrandr_is_current_fix.out
deleted file mode 100644
index 452a6462..00000000
--- a/tests/fixtures/generic/xrandr_is_current_fix.out
+++ /dev/null
@@ -1,44 +0,0 @@
-Screen 0: minimum 320 x 200, current 1846 x 768, maximum 8192 x 8192
-LVDS-1 connected primary 1366x768+0+0 (normal left inverted right x axis y axis) 344mm x 194mm
- 1366x768 60.00*+
- 1280x720 60.00 59.99 59.86 59.74
- 1024x768 60.04 60.00
- 960x720 60.00
- 928x696 60.05
- 896x672 60.01
- 1024x576 59.95 59.96 59.90 59.82
- 960x600 59.93 60.00
- 960x540 59.96 59.99 59.63 59.82
- 800x600 60.00 60.32 56.25
- 840x525 60.01 59.88
- 864x486 59.92 59.57
- 700x525 59.98
- 800x450 59.95 59.82
- 640x512 60.02
- 700x450 59.96 59.88
- 640x480 60.00 59.94
- 720x405 59.51 58.99
- 684x384 59.88 59.85
- 640x400 59.88 59.98
- 640x360 59.86 59.83 59.84 59.32
- 512x384 60.00
- 512x288 60.00 59.92
- 480x270 59.63 59.82
- 400x300 60.32 56.34
- 432x243 59.92 59.57
- 320x240 60.05
- 360x202 59.51 59.13
- 320x180 59.84 59.32
-VGA-1 connected 480x640+1366+0 left (normal left inverted right x axis y axis) 408mm x 255mm
- 1440x900 59.89 + 74.98
- 1280x1024 75.02 60.02
- 1280x960 60.00
- 1280x800 74.93 59.81
- 1152x864 75.00
- 1024x768 75.03 70.07 60.00
- 832x624 74.55
- 800x600 72.19 75.00 60.32 56.25
- 640x480 75.00* 72.81 66.67 59.94
- 720x400 70.08
-HDMI-1 disconnected (normal left inverted right x axis y axis)
-DP-1 disconnected (normal left inverted right x axis y axis)
diff --git a/tests/fixtures/pi/ping-ip-O-D-streaming.json b/tests/fixtures/pi/ping-ip-O-D-streaming.json
index 55c79d86..243799c6 100644
--- a/tests/fixtures/pi/ping-ip-O-D-streaming.json
+++ b/tests/fixtures/pi/ping-ip-O-D-streaming.json
@@ -1 +1 @@
-[{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":1596585008.591169,"icmp_seq":1},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":1596585009.631169,"icmp_seq":2},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":1596585010.671173,"icmp_seq":3},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":1596585011.711167,"icmp_seq":4}]
+[{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":1596585008.591169,"icmp_seq":1},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":1596585009.631169,"icmp_seq":2},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":1596585010.671173,"icmp_seq":3},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":1596585011.711167,"icmp_seq":4},{"type":"summary","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"packets_transmitted":5,"packets_received":0,"packet_loss_percent":100.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":4154.0,"round_trip_ms_min":null,"round_trip_ms_avg":null,"round_trip_ms_max":null,"round_trip_ms_stddev":null}]
diff --git a/tests/fixtures/pi/ping-ip-O-streaming.json b/tests/fixtures/pi/ping-ip-O-streaming.json
index adf1f705..379066e5 100644
--- a/tests/fixtures/pi/ping-ip-O-streaming.json
+++ b/tests/fixtures/pi/ping-ip-O-streaming.json
@@ -1 +1 @@
-[{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":1},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":2},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":3},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":4}]
+[{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":1},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":2},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":3},{"type":"timeout","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"timestamp":null,"icmp_seq":4},{"type":"summary","destination_ip":"192.168.120.164","sent_bytes":56,"pattern":null,"packets_transmitted":5,"packets_received":0,"packet_loss_percent":100.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":4149.0,"round_trip_ms_min":null,"round_trip_ms_avg":null,"round_trip_ms_max":null,"round_trip_ms_stddev":null}]
diff --git a/tests/fixtures/ubuntu-18.04/ping-hostname-O-D-p-s-streaming.json b/tests/fixtures/ubuntu-18.04/ping-hostname-O-D-p-s-streaming.json
index a8a5088c..4c74ccca 100644
--- a/tests/fixtures/ubuntu-18.04/ping-hostname-O-D-p-s-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping-hostname-O-D-p-s-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103464.996693,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":26.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103466.001289,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":28.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103467.004316,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":28.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103468.009966,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":33.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103469.013655,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103470.014253,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":34.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103471.02653,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":44.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103472.019493,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103473.021432,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":35.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103474.015603,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":27.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103475.02676,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":36.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103476.02693,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":35.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103477.031093,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":36.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103478.028918,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":33.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103479.032238,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":15,"ttl":59,"time_ms":35.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103480.032097,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":33.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103481.034546,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":34.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103482.037939,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":35.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103483.041514,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103484.03911,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":29.3,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19040.0,"round_trip_ms_min":26.767,"round_trip_ms_avg":33.782,"round_trip_ms_max":44.159,"round_trip_ms_stddev":3.954}]
+[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103464.996693,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":26.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103466.001289,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":28.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103467.004316,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":28.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103468.009966,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":33.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103469.013655,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103470.014253,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":34.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103471.02653,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":44.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103472.019493,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":34.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103473.021432,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":35.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103474.015603,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":27.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103475.02676,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":36.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103476.02693,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":35.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103477.031093,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":36.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103478.028918,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":33.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103479.032238,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":15,"ttl":59,"time_ms":35.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103480.032097,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":33.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103481.034546,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":34.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103482.037939,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":35.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103483.041514,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":35.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595103484.03911,"response_bytes":1408,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":29.3,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19040.0,"round_trip_ms_min":26.767,"round_trip_ms_avg":33.782,"round_trip_ms_max":44.159,"round_trip_ms_stddev":3.954}]
diff --git a/tests/fixtures/ubuntu-18.04/ping-hostname-O-p-streaming.json b/tests/fixtures/ubuntu-18.04/ping-hostname-O-p-streaming.json
index 78edc0f8..ce7faabd 100644
--- a/tests/fixtures/ubuntu-18.04/ping-hostname-O-p-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping-hostname-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":26.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":26.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":34.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":34.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":25.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":33.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":34.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":27.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":32.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":32.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":24.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":15,"ttl":59,"time_ms":35.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":33.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":74.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":31.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":85.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":143.0,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19052.0,"round_trip_ms_min":24.785,"round_trip_ms_avg":41.856,"round_trip_ms_max":143.789,"round_trip_ms_stddev":27.768}]
+[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":26.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":26.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":34.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":34.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":25.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":33.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":34.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":27.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":32.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":32.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":32.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":24.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":15,"ttl":59,"time_ms":35.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":33.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":74.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":31.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":85.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":143.0,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19052.0,"round_trip_ms_min":24.785,"round_trip_ms_avg":41.856,"round_trip_ms_max":143.789,"round_trip_ms_stddev":27.768}]
diff --git a/tests/fixtures/ubuntu-18.04/ping-hostname-O-streaming.json b/tests/fixtures/ubuntu-18.04/ping-hostname-O-streaming.json
index 870708ae..1a0824f2 100644
--- a/tests/fixtures/ubuntu-18.04/ping-hostname-O-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping-hostname-O-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":26.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":24.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":32.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":33.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":32.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":26.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":34.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":24.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":34.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":33.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":33.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":33.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":26.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":15,"ttl":59,"time_ms":27.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":33.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":35.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":26.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":34.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":27.1,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19290.0,"round_trip_ms_min":24.33,"round_trip_ms_avg":30.42,"round_trip_ms_max":35.259,"round_trip_ms_stddev":3.84}]
+[{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":1,"ttl":59,"time_ms":26.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":2,"ttl":59,"time_ms":24.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":3,"ttl":59,"time_ms":32.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":4,"ttl":59,"time_ms":33.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":5,"ttl":59,"time_ms":32.5,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":6,"ttl":59,"time_ms":26.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":7,"ttl":59,"time_ms":34.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":8,"ttl":59,"time_ms":24.6,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":9,"ttl":59,"time_ms":34.7,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":10,"ttl":59,"time_ms":33.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":11,"ttl":59,"time_ms":33.9,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":12,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":13,"ttl":59,"time_ms":33.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":14,"ttl":59,"time_ms":26.3,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":15,"ttl":59,"time_ms":27.0,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":16,"ttl":59,"time_ms":33.8,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":17,"ttl":59,"time_ms":35.2,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":18,"ttl":59,"time_ms":26.4,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":19,"ttl":59,"time_ms":34.1,"duplicate":false},{"type":"reply","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"151.101.189.67","icmp_seq":20,"ttl":59,"time_ms":27.1,"duplicate":false},{"type":"summary","destination_ip":"151.101.189.67","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19290.0,"round_trip_ms_min":24.33,"round_trip_ms_avg":30.42,"round_trip_ms_max":35.259,"round_trip_ms_stddev":3.84}]
diff --git a/tests/fixtures/ubuntu-18.04/ping-ip-O-D-streaming.json b/tests/fixtures/ubuntu-18.04/ping-ip-O-D-streaming.json
index f5dfcd1e..45172302 100644
--- a/tests/fixtures/ubuntu-18.04/ping-ip-O-D-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping-ip-O-D-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102903.313934,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.017,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102904.33341,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.033,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102905.35791,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.041,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102906.3814,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.039,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102907.406752,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102908.430739,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102909.454753,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102910.478765,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102911.50115,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.027,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102912.525888,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102913.550088,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102914.574405,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.04,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102915.598696,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102916.622554,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.049,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102917.646755,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102918.670765,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102919.693157,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102920.717034,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.038,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102921.741629,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102922.766421,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19452.0,"round_trip_ms_min":0.017,"round_trip_ms_avg":0.044,"round_trip_ms_max":0.051,"round_trip_ms_stddev":0.01}]
+[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102903.313934,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.017,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102904.33341,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.033,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102905.35791,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.041,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102906.3814,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.039,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102907.406752,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102908.430739,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102909.454753,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102910.478765,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102911.50115,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.027,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102912.525888,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102913.550088,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102914.574405,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.04,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102915.598696,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102916.622554,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.049,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102917.646755,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102918.670765,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102919.693157,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102920.717034,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.038,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102921.741629,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":1595102922.766421,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19452.0,"round_trip_ms_min":0.017,"round_trip_ms_avg":0.044,"round_trip_ms_max":0.051,"round_trip_ms_stddev":0.01}]
diff --git a/tests/fixtures/ubuntu-18.04/ping-ip-O-streaming.json b/tests/fixtures/ubuntu-18.04/ping-ip-O-streaming.json
index acbd92e3..4c96172a 100644
--- a/tests/fixtures/ubuntu-18.04/ping-ip-O-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping-ip-O-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.02,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.027,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.041,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.052,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.057,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.049,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19434.0,"round_trip_ms_min":0.02,"round_trip_ms_avg":0.047,"round_trip_ms_max":0.057,"round_trip_ms_stddev":0.01}]
+[{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":1,"ttl":64,"time_ms":0.02,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":2,"ttl":64,"time_ms":0.043,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":3,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":4,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":5,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":6,"ttl":64,"time_ms":0.027,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":7,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":8,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":9,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":10,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":11,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":12,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":13,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":14,"ttl":64,"time_ms":0.041,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":15,"ttl":64,"time_ms":0.052,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":16,"ttl":64,"time_ms":0.057,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":17,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":18,"ttl":64,"time_ms":0.051,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":19,"ttl":64,"time_ms":0.05,"duplicate":false},{"type":"reply","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"timestamp":null,"response_bytes":64,"response_ip":"127.0.0.1","icmp_seq":20,"ttl":64,"time_ms":0.049,"duplicate":false},{"type":"summary","destination_ip":"127.0.0.1","sent_bytes":56,"pattern":null,"packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19434.0,"round_trip_ms_min":0.02,"round_trip_ms_avg":0.047,"round_trip_ms_max":0.057,"round_trip_ms_stddev":0.01}]
diff --git a/tests/fixtures/ubuntu-18.04/ping6-hostname-O-D-p-s-streaming.json b/tests/fixtures/ubuntu-18.04/ping6-hostname-O-D-p-s-streaming.json
index 8baeb712..d39b948d 100644
--- a/tests/fixtures/ubuntu-18.04/ping6-hostname-O-D-p-s-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping6-hostname-O-D-p-s-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102963.207191,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":1,"ttl":59,"time_ms":162.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102964.072572,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":2,"ttl":59,"time_ms":26.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102965.083093,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":3,"ttl":59,"time_ms":34.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102966.086221,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":4,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102967.088365,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":5,"ttl":59,"time_ms":32.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102968.090956,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":6,"ttl":59,"time_ms":33.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102969.088229,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":7,"ttl":59,"time_ms":27.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102970.08863,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":8,"ttl":59,"time_ms":25.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102971.093828,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":9,"ttl":59,"time_ms":27.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102972.104782,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":10,"ttl":59,"time_ms":35.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102973.098518,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":11,"ttl":59,"time_ms":27.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102974.108744,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":12,"ttl":59,"time_ms":36.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102975.104919,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":13,"ttl":59,"time_ms":30.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102976.103486,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":14,"ttl":59,"time_ms":26.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102977.107027,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":15,"ttl":59,"time_ms":27.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102978.111345,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":16,"ttl":59,"time_ms":28.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102979.121028,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":17,"ttl":59,"time_ms":35.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102980.116465,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":18,"ttl":59,"time_ms":28.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102981.126039,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":19,"ttl":59,"time_ms":34.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102982.12868,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":20,"ttl":59,"time_ms":34.3,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"time_ms":19050.0,"round_trip_ms_min":25.086,"round_trip_ms_avg":37.398,"round_trip_ms_max":162.132,"round_trip_ms_stddev":28.854}]
+[{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102963.207191,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":1,"ttl":59,"time_ms":162.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102964.072572,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":2,"ttl":59,"time_ms":26.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102965.083093,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":3,"ttl":59,"time_ms":34.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102966.086221,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":4,"ttl":59,"time_ms":34.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102967.088365,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":5,"ttl":59,"time_ms":32.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102968.090956,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":6,"ttl":59,"time_ms":33.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102969.088229,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":7,"ttl":59,"time_ms":27.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102970.08863,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":8,"ttl":59,"time_ms":25.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102971.093828,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":9,"ttl":59,"time_ms":27.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102972.104782,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":10,"ttl":59,"time_ms":35.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102973.098518,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":11,"ttl":59,"time_ms":27.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102974.108744,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":12,"ttl":59,"time_ms":36.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102975.104919,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":13,"ttl":59,"time_ms":30.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102976.103486,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":14,"ttl":59,"time_ms":26.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102977.107027,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":15,"ttl":59,"time_ms":27.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102978.111345,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":16,"ttl":59,"time_ms":28.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102979.121028,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":17,"ttl":59,"time_ms":35.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102980.116465,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":18,"ttl":59,"time_ms":28.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102981.126039,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":19,"ttl":59,"time_ms":34.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","timestamp":1595102982.12868,"response_bytes":1408,"response_ip":"2a04:4e42:2d::323","icmp_seq":20,"ttl":59,"time_ms":34.3,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:2d::323","sent_bytes":1400,"pattern":"0xabcd","packets_transmitted":20,"packets_received":20,"packet_loss_percent":0.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19050.0,"round_trip_ms_min":25.086,"round_trip_ms_avg":37.398,"round_trip_ms_max":162.132,"round_trip_ms_stddev":28.854}]
diff --git a/tests/fixtures/ubuntu-18.04/ping6-hostname-O-p-streaming.json b/tests/fixtures/ubuntu-18.04/ping6-hostname-O-p-streaming.json
index 461080e0..df3ad4f9 100644
--- a/tests/fixtures/ubuntu-18.04/ping6-hostname-O-p-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping6-hostname-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":1,"ttl":59,"time_ms":25.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":2,"ttl":59,"time_ms":27.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":3,"ttl":59,"time_ms":26.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":4,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":5,"ttl":59,"time_ms":27.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":6,"ttl":59,"time_ms":34.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":7,"ttl":59,"time_ms":26.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":8,"ttl":59,"time_ms":35.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":9,"ttl":59,"time_ms":26.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":10,"ttl":59,"time_ms":33.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":11,"ttl":59,"time_ms":33.5,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":12},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":13,"ttl":59,"time_ms":25.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":14,"ttl":59,"time_ms":25.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":15,"ttl":59,"time_ms":36.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":16,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":17,"ttl":59,"time_ms":35.4,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":18},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":19,"ttl":59,"time_ms":151.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":20,"ttl":59,"time_ms":51.5,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":18,"packet_loss_percent":10.0,"duplicates":0,"time_ms":19081.0,"round_trip_ms_min":25.229,"round_trip_ms_avg":38.451,"round_trip_ms_max":151.911,"round_trip_ms_stddev":28.221}]
+[{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":1,"ttl":59,"time_ms":25.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":2,"ttl":59,"time_ms":27.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":3,"ttl":59,"time_ms":26.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":4,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":5,"ttl":59,"time_ms":27.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":6,"ttl":59,"time_ms":34.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":7,"ttl":59,"time_ms":26.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":8,"ttl":59,"time_ms":35.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":9,"ttl":59,"time_ms":26.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":10,"ttl":59,"time_ms":33.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":11,"ttl":59,"time_ms":33.5,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":12},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":13,"ttl":59,"time_ms":25.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":14,"ttl":59,"time_ms":25.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":15,"ttl":59,"time_ms":36.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":16,"ttl":59,"time_ms":34.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":17,"ttl":59,"time_ms":35.4,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"icmp_seq":18},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":19,"ttl":59,"time_ms":151.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:2d::323","icmp_seq":20,"ttl":59,"time_ms":51.5,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:2d::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":18,"packet_loss_percent":10.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19081.0,"round_trip_ms_min":25.229,"round_trip_ms_avg":38.451,"round_trip_ms_max":151.911,"round_trip_ms_stddev":28.221}]
diff --git a/tests/fixtures/ubuntu-18.04/ping6-ip-O-D-p-streaming.json b/tests/fixtures/ubuntu-18.04/ping6-ip-O-D-p-streaming.json
index ed7d0859..05388e8f 100644
--- a/tests/fixtures/ubuntu-18.04/ping6-ip-O-D-p-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping6-ip-O-D-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102942.853155,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102943.857295,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":29.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102944.861751,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":31.2,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102946.861681,"icmp_seq":4},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102946.891881,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":30.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102947.884818,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":22.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102948.89152,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":27.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102949.897424,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":30.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102950.89982,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":29.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102951.905148,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":31.3,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102953.901458,"icmp_seq":11},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102953.93159,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102955.918953,"icmp_seq":13},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102956.942898,"icmp_seq":14},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102956.973463,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":30.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102957.966655,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":21.4,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102959.981759,"icmp_seq":17},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102960.035095,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":53.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102961.106079,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":121.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102962.145647,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":159.0,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":15,"packet_loss_percent":25.0,"duplicates":0,"time_ms":19161.0,"round_trip_ms_min":21.405,"round_trip_ms_avg":45.041,"round_trip_ms_max":159.38,"round_trip_ms_stddev":38.693}]
+[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102942.853155,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102943.857295,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":29.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102944.861751,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":31.2,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102946.861681,"icmp_seq":4},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102946.891881,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":30.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102947.884818,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":22.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102948.89152,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":27.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102949.897424,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":30.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102950.89982,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":29.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102951.905148,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":31.3,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102953.901458,"icmp_seq":11},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102953.93159,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102955.918953,"icmp_seq":13},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102956.942898,"icmp_seq":14},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102956.973463,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":30.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102957.966655,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":21.4,"duplicate":false},{"type":"timeout","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102959.981759,"icmp_seq":17},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102960.035095,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":53.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102961.106079,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":121.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":1595102962.145647,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":20,"ttl":59,"time_ms":159.0,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":15,"packet_loss_percent":25.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19161.0,"round_trip_ms_min":21.405,"round_trip_ms_avg":45.041,"round_trip_ms_max":159.38,"round_trip_ms_stddev":38.693}]
diff --git a/tests/fixtures/ubuntu-18.04/ping6-ip-O-p-streaming.json b/tests/fixtures/ubuntu-18.04/ping6-ip-O-p-streaming.json
index e8045c22..9d096c02 100644
--- a/tests/fixtures/ubuntu-18.04/ping6-ip-O-p-streaming.json
+++ b/tests/fixtures/ubuntu-18.04/ping6-ip-O-p-streaming.json
@@ -1 +1 @@
-[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":26.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":24.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":23.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":21.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":23.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":21.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":22.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":22.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":29.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":11,"ttl":59,"time_ms":22.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":22.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":22.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":30.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":24.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":22.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":24.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"time_ms":19046.0,"round_trip_ms_min":21.403,"round_trip_ms_avg":24.901,"round_trip_ms_max":30.176,"round_trip_ms_stddev":3.056}]
+[{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":1,"ttl":59,"time_ms":26.8,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":2,"ttl":59,"time_ms":24.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":3,"ttl":59,"time_ms":23.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":4,"ttl":59,"time_ms":21.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":5,"ttl":59,"time_ms":28.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":6,"ttl":59,"time_ms":23.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":7,"ttl":59,"time_ms":21.4,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":8,"ttl":59,"time_ms":22.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":9,"ttl":59,"time_ms":22.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":10,"ttl":59,"time_ms":29.3,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":11,"ttl":59,"time_ms":22.6,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":12,"ttl":59,"time_ms":22.7,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":13,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":14,"ttl":59,"time_ms":22.0,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":15,"ttl":59,"time_ms":30.1,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":16,"ttl":59,"time_ms":24.2,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":17,"ttl":59,"time_ms":22.9,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":18,"ttl":59,"time_ms":24.5,"duplicate":false},{"type":"reply","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","timestamp":null,"response_bytes":64,"response_ip":"2a04:4e42:600::323","icmp_seq":19,"ttl":59,"time_ms":29.9,"duplicate":false},{"type":"summary","destination_ip":"2a04:4e42:600::323","sent_bytes":56,"pattern":"0xabcd","packets_transmitted":20,"packets_received":19,"packet_loss_percent":5.0,"duplicates":0,"errors":null,"corrupted":null,"time_ms":19046.0,"round_trip_ms_min":21.403,"round_trip_ms_avg":24.901,"round_trip_ms_max":30.176,"round_trip_ms_stddev":3.056}]
diff --git a/tests/fixtures/ubuntu-22.04/ping-dest-unreachable-streaming.json b/tests/fixtures/ubuntu-22.04/ping-dest-unreachable-streaming.json
new file mode 100644
index 00000000..16aae853
--- /dev/null
+++ b/tests/fixtures/ubuntu-22.04/ping-dest-unreachable-streaming.json
@@ -0,0 +1 @@
+{"type":"summary","destination_ip":"10.0.3.22","sent_bytes":56,"pattern":null,"packets_transmitted":3,"packets_received":0,"packet_loss_percent":100.0,"duplicates":0,"errors":3,"corrupted":null,"time_ms":2049.0,"round_trip_ms_min":null,"round_trip_ms_avg":null,"round_trip_ms_max":null,"round_trip_ms_stddev":null}
diff --git a/tests/fixtures/ubuntu-22.04/ping-dest-unreachable.json b/tests/fixtures/ubuntu-22.04/ping-dest-unreachable.json
new file mode 100644
index 00000000..e13a2c85
--- /dev/null
+++ b/tests/fixtures/ubuntu-22.04/ping-dest-unreachable.json
@@ -0,0 +1 @@
+{"destination_ip":"10.0.3.22","data_bytes":56,"pattern":null,"destination":"10.0.3.22","duplicates":0,"packets_transmitted":3,"packets_received":0,"errors":3,"packet_loss_percent":100.0,"time_ms":2049.0,"responses":[]}
diff --git a/tests/fixtures/ubuntu-22.04/ping-dest-unreachable.out b/tests/fixtures/ubuntu-22.04/ping-dest-unreachable.out
new file mode 100644
index 00000000..56c970ab
--- /dev/null
+++ b/tests/fixtures/ubuntu-22.04/ping-dest-unreachable.out
@@ -0,0 +1,8 @@
+PING 10.0.3.22 (10.0.3.22) 56(84) bytes of data.
+From 10.0.0.1 icmp_seq=1 Destination Host Unreachable
+From 10.0.0.1 icmp_seq=2 Destination Host Unreachable
+From 10.0.0.1 icmp_seq=3 Destination Host Unreachable
+
+--- 10.0.3.22 ping statistics ---
+3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2049ms
+pipe 3
diff --git a/tests/test_env.py b/tests/test_env.py
index a0144dca..d76c61d2 100644
--- a/tests/test_env.py
+++ b/tests/test_env.py
@@ -7,6 +7,7 @@ THIS_DIR = os.path.dirname(os.path.abspath(__file__))
class MyTests(unittest.TestCase):
+ maxDiff = None
# input
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/env.out'), 'r', encoding='utf-8') as f:
@@ -15,6 +16,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/env.out'), 'r', encoding='utf-8') as f:
ubuntu_18_4_env = f.read()
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/env-multiline.out'), 'r', encoding='utf-8') as f:
+ env_multiline = f.read()
+
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/env.json'), 'r', encoding='utf-8') as f:
centos_7_7_env_json = json.loads(f.read())
@@ -22,6 +26,12 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/env.json'), 'r', encoding='utf-8') as f:
ubuntu_18_4_env_json = json.loads(f.read())
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/env-multiline.json'), 'r', encoding='utf-8') as f:
+ env_multiline_json = json.loads(f.read())
+
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/env-multiline-raw.json'), 'r', encoding='utf-8') as f:
+ env_multiline_raw_json = json.loads(f.read())
+
def test_env_nodata(self):
"""
@@ -41,6 +51,18 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.env.parse(self.ubuntu_18_4_env, quiet=True), self.ubuntu_18_4_env_json)
+ def test_env_multiline(self):
+ """
+ Test 'env' with multiline value
+ """
+ self.assertEqual(jc.parsers.env.parse(self.env_multiline, quiet=True), self.env_multiline_json)
+
+ def test_env_multiline_raw(self):
+ """
+ Test 'env' with multiline value with raw output
+ """
+ self.assertEqual(jc.parsers.env.parse(self.env_multiline, quiet=True, raw=True), self.env_multiline_raw_json)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_host.py b/tests/test_host.py
new file mode 100644
index 00000000..47d024bb
--- /dev/null
+++ b/tests/test_host.py
@@ -0,0 +1,58 @@
+import os
+import unittest
+import json
+from typing import Dict
+from jc.parsers.host import parse
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+class MyTests(unittest.TestCase):
+ f_in: Dict = {}
+ f_json: Dict = {}
+
+ @classmethod
+ def setUpClass(cls):
+ fixtures = {
+ 'google': (
+ 'fixtures/generic/host-google.out',
+ 'fixtures/generic/host-google.json'),
+ 'sunet': (
+ 'fixtures/generic/host-sunet.out',
+ 'fixtures/generic/host-sunet.json')
+ }
+
+ for file, filepaths in fixtures.items():
+ with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \
+ open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b:
+ cls.f_in[file] = a.read()
+ cls.f_json[file] = json.loads(b.read())
+
+ # host cannot run without input (will only display help)
+ def test_host_nodata(self):
+ """
+ Test 'host' with no data
+ """
+ self.assertEqual(parse('', quiet=True), [])
+
+
+ def test_host_google(self):
+ """
+ Test 'host google'
+ """
+ self.assertEqual(
+ parse(self.f_in['google'], quiet=True),
+ self.f_json['google']
+ )
+
+ def test_host_sunet(self):
+ """
+ Test 'host sunet'
+ """
+ self.assertEqual(
+ parse(self.f_in['sunet'], quiet=True),
+ self.f_json['sunet']
+ )
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_jc_cli.py b/tests/test_jc_cli.py
index 5bfc13d2..aad514f9 100644
--- a/tests/test_jc_cli.py
+++ b/tests/test_jc_cli.py
@@ -1,8 +1,12 @@
import os
import unittest
from datetime import datetime, timezone
-import pygments
-from pygments.token import (Name, Number, String, Keyword)
+try:
+ import pygments
+ from pygments.token import (Name, Number, String, Keyword)
+ PYGMENTS_INSTALLED=True
+except ModuleNotFoundError:
+ PYGMENTS_INSTALLED=False
from jc.cli import JcCli
@@ -42,216 +46,220 @@ class MyTests(unittest.TestCase):
self.assertEqual(expected, resulting_attributes)
def test_cli_set_env_colors(self):
- if pygments.__version__.startswith('2.3.'):
- env = {
- '': {
- Name.Tag: 'bold #ansidarkblue',
- Keyword: '#ansidarkgray',
- Number: '#ansipurple',
- String: '#ansidarkgreen'
- },
- ' ': {
- Name.Tag: 'bold #ansidarkblue',
- Keyword: '#ansidarkgray',
- Number: '#ansipurple',
- String: '#ansidarkgreen'
- },
- 'default,default,default,default': {
- Name.Tag: 'bold #ansidarkblue',
- Keyword: '#ansidarkgray',
- Number: '#ansipurple',
- String: '#ansidarkgreen'
- },
- 'red,red,red,red': {
- Name.Tag: 'bold #ansidarkred',
- Keyword: '#ansidarkred',
- Number: '#ansidarkred',
- String: '#ansidarkred'
- },
- 'red,red,yada,red': {
- Name.Tag: 'bold #ansidarkblue',
- Keyword: '#ansidarkgray',
- Number: '#ansipurple',
- String: '#ansidarkgreen'
- },
- 'red,red,red': {
- Name.Tag: 'bold #ansidarkblue',
- Keyword: '#ansidarkgray',
- Number: '#ansipurple',
- String: '#ansidarkgreen'
- },
- 'red,red,red,red,red,red': {
- Name.Tag: 'bold #ansidarkblue',
- Keyword: '#ansidarkgray',
- Number: '#ansipurple',
- String: '#ansidarkgreen'
+ if PYGMENTS_INSTALLED:
+ if pygments.__version__.startswith('2.3.'):
+ env = {
+ '': {
+ Name.Tag: 'bold #ansidarkblue',
+ Keyword: '#ansidarkgray',
+ Number: '#ansipurple',
+ String: '#ansidarkgreen'
+ },
+ ' ': {
+ Name.Tag: 'bold #ansidarkblue',
+ Keyword: '#ansidarkgray',
+ Number: '#ansipurple',
+ String: '#ansidarkgreen'
+ },
+ 'default,default,default,default': {
+ Name.Tag: 'bold #ansidarkblue',
+ Keyword: '#ansidarkgray',
+ Number: '#ansipurple',
+ String: '#ansidarkgreen'
+ },
+ 'red,red,red,red': {
+ Name.Tag: 'bold #ansidarkred',
+ Keyword: '#ansidarkred',
+ Number: '#ansidarkred',
+ String: '#ansidarkred'
+ },
+ 'red,red,yada,red': {
+ Name.Tag: 'bold #ansidarkblue',
+ Keyword: '#ansidarkgray',
+ Number: '#ansipurple',
+ String: '#ansidarkgreen'
+ },
+ 'red,red,red': {
+ Name.Tag: 'bold #ansidarkblue',
+ Keyword: '#ansidarkgray',
+ Number: '#ansipurple',
+ String: '#ansidarkgreen'
+ },
+ 'red,red,red,red,red,red': {
+ Name.Tag: 'bold #ansidarkblue',
+ Keyword: '#ansidarkgray',
+ Number: '#ansipurple',
+ String: '#ansidarkgreen'
+ }
}
- }
- else:
- env = {
- '': {
- Name.Tag: 'bold ansiblue',
- Keyword: 'ansibrightblack',
- Number: 'ansimagenta',
- String: 'ansigreen'
- },
- ' ': {
- Name.Tag: 'bold ansiblue',
- Keyword: 'ansibrightblack',
- Number: 'ansimagenta',
- String: 'ansigreen'
- },
- 'default,default,default,default': {
- Name.Tag: 'bold ansiblue',
- Keyword: 'ansibrightblack',
- Number: 'ansimagenta',
- String: 'ansigreen'
- },
- 'red,red,red,red': {
- Name.Tag: 'bold ansired',
- Keyword: 'ansired',
- Number: 'ansired',
- String: 'ansired'
- },
- 'red,red,yada,red': {
- Name.Tag: 'bold ansiblue',
- Keyword: 'ansibrightblack',
- Number: 'ansimagenta',
- String: 'ansigreen'
- },
- 'red,red,red': {
- Name.Tag: 'bold ansiblue',
- Keyword: 'ansibrightblack',
- Number: 'ansimagenta',
- String: 'ansigreen'
- },
- 'red,red,red,red,red,red': {
- Name.Tag: 'bold ansiblue',
- Keyword: 'ansibrightblack',
- Number: 'ansimagenta',
- String: 'ansigreen'
+ else:
+ env = {
+ '': {
+ Name.Tag: 'bold ansiblue',
+ Keyword: 'ansibrightblack',
+ Number: 'ansimagenta',
+ String: 'ansigreen'
+ },
+ ' ': {
+ Name.Tag: 'bold ansiblue',
+ Keyword: 'ansibrightblack',
+ Number: 'ansimagenta',
+ String: 'ansigreen'
+ },
+ 'default,default,default,default': {
+ Name.Tag: 'bold ansiblue',
+ Keyword: 'ansibrightblack',
+ Number: 'ansimagenta',
+ String: 'ansigreen'
+ },
+ 'red,red,red,red': {
+ Name.Tag: 'bold ansired',
+ Keyword: 'ansired',
+ Number: 'ansired',
+ String: 'ansired'
+ },
+ 'red,red,yada,red': {
+ Name.Tag: 'bold ansiblue',
+ Keyword: 'ansibrightblack',
+ Number: 'ansimagenta',
+ String: 'ansigreen'
+ },
+ 'red,red,red': {
+ Name.Tag: 'bold ansiblue',
+ Keyword: 'ansibrightblack',
+ Number: 'ansimagenta',
+ String: 'ansigreen'
+ },
+ 'red,red,red,red,red,red': {
+ Name.Tag: 'bold ansiblue',
+ Keyword: 'ansibrightblack',
+ Number: 'ansimagenta',
+ String: 'ansigreen'
+ }
}
- }
- for jc_colors, expected_colors in env.items():
- cli = JcCli()
- os.environ["JC_COLORS"] = jc_colors
- cli.set_custom_colors()
- self.assertEqual(cli.custom_colors, expected_colors)
+ for jc_colors, expected_colors in env.items():
+ cli = JcCli()
+ os.environ["JC_COLORS"] = jc_colors
+ cli.set_custom_colors()
+ self.assertEqual(cli.custom_colors, expected_colors)
def test_cli_json_out(self):
- test_input = [
- None,
- {},
- [],
- '',
- {"key1": "value1", "key2": 2, "key3": None, "key4": 3.14, "key5": True},
- ]
-
- if pygments.__version__.startswith('2.3.'):
- expected_output = [
- '\x1b[30;01mnull\x1b[39;00m',
- '{}',
- '[]',
- '\x1b[32m""\x1b[39m',
- '{\x1b[34;01m"key1"\x1b[39;00m:\x1b[32m"value1"\x1b[39m,\x1b[34;01m"key2"\x1b[39;00m:\x1b[35m2\x1b[39m,\x1b[34;01m"key3"\x1b[39;00m:\x1b[30;01mnull\x1b[39;00m,\x1b[34;01m"key4"\x1b[39;00m:\x1b[35m3.14\x1b[39m,\x1b[34;01m"key5"\x1b[39;00m:\x1b[30;01mtrue\x1b[39;00m}'
- ]
- else:
- expected_output = [
- '\x1b[90mnull\x1b[39m',
- '{}',
- '[]',
- '\x1b[32m""\x1b[39m',
- '{\x1b[34;01m"key1"\x1b[39;00m:\x1b[32m"value1"\x1b[39m,\x1b[34;01m"key2"\x1b[39;00m:\x1b[35m2\x1b[39m,\x1b[34;01m"key3"\x1b[39;00m:\x1b[90mnull\x1b[39m,\x1b[34;01m"key4"\x1b[39;00m:\x1b[35m3.14\x1b[39m,\x1b[34;01m"key5"\x1b[39;00m:\x1b[90mtrue\x1b[39m}'
+ if PYGMENTS_INSTALLED:
+ test_input = [
+ None,
+ {},
+ [],
+ '',
+ {"key1": "value1", "key2": 2, "key3": None, "key4": 3.14, "key5": True},
]
- for test_dict, expected_json in zip(test_input, expected_output):
- cli = JcCli()
- os.environ["JC_COLORS"] = "default,default,default,default"
- cli.set_custom_colors()
- cli.data_out = test_dict
- self.assertEqual(cli.json_out(), expected_json)
+ if pygments.__version__.startswith('2.3.'):
+ expected_output = [
+ '\x1b[30;01mnull\x1b[39;00m',
+ '{}',
+ '[]',
+ '\x1b[32m""\x1b[39m',
+ '{\x1b[34;01m"key1"\x1b[39;00m:\x1b[32m"value1"\x1b[39m,\x1b[34;01m"key2"\x1b[39;00m:\x1b[35m2\x1b[39m,\x1b[34;01m"key3"\x1b[39;00m:\x1b[30;01mnull\x1b[39;00m,\x1b[34;01m"key4"\x1b[39;00m:\x1b[35m3.14\x1b[39m,\x1b[34;01m"key5"\x1b[39;00m:\x1b[30;01mtrue\x1b[39;00m}'
+ ]
+ else:
+ expected_output = [
+ '\x1b[90mnull\x1b[39m',
+ '{}',
+ '[]',
+ '\x1b[32m""\x1b[39m',
+ '{\x1b[34;01m"key1"\x1b[39;00m:\x1b[32m"value1"\x1b[39m,\x1b[34;01m"key2"\x1b[39;00m:\x1b[35m2\x1b[39m,\x1b[34;01m"key3"\x1b[39;00m:\x1b[90mnull\x1b[39m,\x1b[34;01m"key4"\x1b[39;00m:\x1b[35m3.14\x1b[39m,\x1b[34;01m"key5"\x1b[39;00m:\x1b[90mtrue\x1b[39m}'
+ ]
+
+ for test_dict, expected_json in zip(test_input, expected_output):
+ cli = JcCli()
+ os.environ["JC_COLORS"] = "default,default,default,default"
+ cli.set_custom_colors()
+ cli.data_out = test_dict
+ self.assertEqual(cli.json_out(), expected_json)
def test_cli_json_out_mono(self):
- test_input = [
- None,
- {},
- [],
- '',
- {"key1": "value1", "key2": 2, "key3": None, "key4": 3.14, "key5": True},
- ]
-
- expected_output = [
- 'null',
- '{}',
- '[]',
- '""',
- '{"key1":"value1","key2":2,"key3":null,"key4":3.14,"key5":true}'
- ]
-
- for test_dict, expected_json in zip(test_input, expected_output):
- cli = JcCli()
- cli.set_custom_colors()
- cli.mono = True
- cli.data_out = test_dict
- self.assertEqual(cli.json_out(), expected_json)
-
- def test_cli_json_out_pretty(self):
- test_input = [
- {"key1": "value1", "key2": 2, "key3": None, "key4": 3.14, "key5": True},
- {"key1": [{"subkey1": "subvalue1"}, {"subkey2": [1, 2, 3]}], "key2": True}
- ]
-
- if pygments.__version__.startswith('2.3.'):
- expected_output = [
- '{\n \x1b[34;01m"key1"\x1b[39;00m: \x1b[32m"value1"\x1b[39m,\n \x1b[34;01m"key2"\x1b[39;00m: \x1b[35m2\x1b[39m,\n \x1b[34;01m"key3"\x1b[39;00m: \x1b[30;01mnull\x1b[39;00m,\n \x1b[34;01m"key4"\x1b[39;00m: \x1b[35m3.14\x1b[39m,\n \x1b[34;01m"key5"\x1b[39;00m: \x1b[30;01mtrue\x1b[39;00m\n}',
- '{\n \x1b[34;01m"key1"\x1b[39;00m: [\n {\n \x1b[34;01m"subkey1"\x1b[39;00m: \x1b[32m"subvalue1"\x1b[39m\n },\n {\n \x1b[34;01m"subkey2"\x1b[39;00m: [\n \x1b[35m1\x1b[39m,\n \x1b[35m2\x1b[39m,\n \x1b[35m3\x1b[39m\n ]\n }\n ],\n \x1b[34;01m"key2"\x1b[39;00m: \x1b[30;01mtrue\x1b[39;00m\n}'
- ]
- else:
- expected_output = [
- '{\n \x1b[34;01m"key1"\x1b[39;00m: \x1b[32m"value1"\x1b[39m,\n \x1b[34;01m"key2"\x1b[39;00m: \x1b[35m2\x1b[39m,\n \x1b[34;01m"key3"\x1b[39;00m: \x1b[90mnull\x1b[39m,\n \x1b[34;01m"key4"\x1b[39;00m: \x1b[35m3.14\x1b[39m,\n \x1b[34;01m"key5"\x1b[39;00m: \x1b[90mtrue\x1b[39m\n}',
- '{\n \x1b[34;01m"key1"\x1b[39;00m: [\n {\n \x1b[34;01m"subkey1"\x1b[39;00m: \x1b[32m"subvalue1"\x1b[39m\n },\n {\n \x1b[34;01m"subkey2"\x1b[39;00m: [\n \x1b[35m1\x1b[39m,\n \x1b[35m2\x1b[39m,\n \x1b[35m3\x1b[39m\n ]\n }\n ],\n \x1b[34;01m"key2"\x1b[39;00m: \x1b[90mtrue\x1b[39m\n}'
+ if PYGMENTS_INSTALLED:
+ test_input = [
+ None,
+ {},
+ [],
+ '',
+ {"key1": "value1", "key2": 2, "key3": None, "key4": 3.14, "key5": True},
]
- for test_dict, expected_json in zip(test_input, expected_output):
- cli = JcCli()
- cli.pretty = True
- cli.set_custom_colors()
- cli.data_out = test_dict
- self.assertEqual(cli.json_out(), expected_json)
+ expected_output = [
+ 'null',
+ '{}',
+ '[]',
+ '""',
+ '{"key1":"value1","key2":2,"key3":null,"key4":3.14,"key5":true}'
+ ]
+
+ for test_dict, expected_json in zip(test_input, expected_output):
+ cli = JcCli()
+ cli.set_custom_colors()
+ cli.mono = True
+ cli.data_out = test_dict
+ self.assertEqual(cli.json_out(), expected_json)
+
+ def test_cli_json_out_pretty(self):
+ test_input = [
+ {"key1": "value1", "key2": 2, "key3": None, "key4": 3.14, "key5": True},
+ {"key1": [{"subkey1": "subvalue1"}, {"subkey2": [1, 2, 3]}], "key2": True}
+ ]
+
+ if pygments.__version__.startswith('2.3.'):
+ expected_output = [
+ '{\n \x1b[34;01m"key1"\x1b[39;00m: \x1b[32m"value1"\x1b[39m,\n \x1b[34;01m"key2"\x1b[39;00m: \x1b[35m2\x1b[39m,\n \x1b[34;01m"key3"\x1b[39;00m: \x1b[30;01mnull\x1b[39;00m,\n \x1b[34;01m"key4"\x1b[39;00m: \x1b[35m3.14\x1b[39m,\n \x1b[34;01m"key5"\x1b[39;00m: \x1b[30;01mtrue\x1b[39;00m\n}',
+ '{\n \x1b[34;01m"key1"\x1b[39;00m: [\n {\n \x1b[34;01m"subkey1"\x1b[39;00m: \x1b[32m"subvalue1"\x1b[39m\n },\n {\n \x1b[34;01m"subkey2"\x1b[39;00m: [\n \x1b[35m1\x1b[39m,\n \x1b[35m2\x1b[39m,\n \x1b[35m3\x1b[39m\n ]\n }\n ],\n \x1b[34;01m"key2"\x1b[39;00m: \x1b[30;01mtrue\x1b[39;00m\n}'
+ ]
+ else:
+ expected_output = [
+ '{\n \x1b[34;01m"key1"\x1b[39;00m: \x1b[32m"value1"\x1b[39m,\n \x1b[34;01m"key2"\x1b[39;00m: \x1b[35m2\x1b[39m,\n \x1b[34;01m"key3"\x1b[39;00m: \x1b[90mnull\x1b[39m,\n \x1b[34;01m"key4"\x1b[39;00m: \x1b[35m3.14\x1b[39m,\n \x1b[34;01m"key5"\x1b[39;00m: \x1b[90mtrue\x1b[39m\n}',
+ '{\n \x1b[34;01m"key1"\x1b[39;00m: [\n {\n \x1b[34;01m"subkey1"\x1b[39;00m: \x1b[32m"subvalue1"\x1b[39m\n },\n {\n \x1b[34;01m"subkey2"\x1b[39;00m: [\n \x1b[35m1\x1b[39m,\n \x1b[35m2\x1b[39m,\n \x1b[35m3\x1b[39m\n ]\n }\n ],\n \x1b[34;01m"key2"\x1b[39;00m: \x1b[90mtrue\x1b[39m\n}'
+ ]
+
+ for test_dict, expected_json in zip(test_input, expected_output):
+ cli = JcCli()
+ cli.pretty = True
+ cli.set_custom_colors()
+ cli.data_out = test_dict
+ self.assertEqual(cli.json_out(), expected_json)
def test_cli_yaml_out(self):
- test_input = [
- None,
- {},
- [],
- '',
- {"key1": "value1", "key2": 2, "key3": None, "key4": 3.14, "key5": True},
- ]
-
- if pygments.__version__.startswith('2.3.'):
- expected_output = [
- '---\n...',
- '--- {}',
- '--- []',
- "--- \x1b[32m'\x1b[39m\x1b[32m'\x1b[39m",
- '---\nkey1: value1\nkey2: 2\nkey3:\nkey4: 3.14\nkey5: true'
- ]
- else:
- expected_output = [
- '---\n...',
- '--- {}',
- '--- []',
- "--- \x1b[32m'\x1b[39m\x1b[32m'\x1b[39m",
- '---\n\x1b[34;01mkey1\x1b[39;00m: value1\n\x1b[34;01mkey2\x1b[39;00m: 2\n\x1b[34;01mkey3\x1b[39;00m:\n\x1b[34;01mkey4\x1b[39;00m: 3.14\n\x1b[34;01mkey5\x1b[39;00m: true'
+ if PYGMENTS_INSTALLED:
+ test_input = [
+ None,
+ {},
+ [],
+ '',
+ {"key1": "value1", "key2": 2, "key3": None, "key4": 3.14, "key5": True},
]
- for test_dict, expected_json in zip(test_input, expected_output):
- cli = JcCli()
- os.environ["JC_COLORS"] = "default,default,default,default"
- cli.set_custom_colors()
- cli.data_out = test_dict
- self.assertEqual(cli.yaml_out(), expected_json)
+ if pygments.__version__.startswith('2.3.'):
+ expected_output = [
+ '---\n...',
+ '--- {}',
+ '--- []',
+ "--- \x1b[32m'\x1b[39m\x1b[32m'\x1b[39m",
+ '---\nkey1: value1\nkey2: 2\nkey3:\nkey4: 3.14\nkey5: true'
+ ]
+ else:
+ expected_output = [
+ '---\n...',
+ '--- {}',
+ '--- []',
+ "--- \x1b[32m'\x1b[39m\x1b[32m'\x1b[39m",
+ '---\n\x1b[34;01mkey1\x1b[39;00m: value1\n\x1b[34;01mkey2\x1b[39;00m: 2\n\x1b[34;01mkey3\x1b[39;00m:\n\x1b[34;01mkey4\x1b[39;00m: 3.14\n\x1b[34;01mkey5\x1b[39;00m: true'
+ ]
+
+ for test_dict, expected_json in zip(test_input, expected_output):
+ cli = JcCli()
+ os.environ["JC_COLORS"] = "default,default,default,default"
+ cli.set_custom_colors()
+ cli.data_out = test_dict
+ self.assertEqual(cli.yaml_out(), expected_json)
def test_cli_yaml_out_mono(self):
test_input = [
diff --git a/tests/test_lsb_release.py b/tests/test_lsb_release.py
new file mode 100644
index 00000000..5e2695c1
--- /dev/null
+++ b/tests/test_lsb_release.py
@@ -0,0 +1,47 @@
+import os
+import unittest
+import json
+from typing import Dict
+from jc.parsers.lsb_release import parse
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+class MyTests(unittest.TestCase):
+ f_in: Dict = {}
+ f_json: Dict = {}
+
+ @classmethod
+ def setUpClass(cls):
+ fixtures = {
+ 'lsb_release_a': (
+ 'fixtures/generic/lsb_release-a.out',
+ 'fixtures/generic/lsb_release-a.json')
+ }
+
+ for file, filepaths in fixtures.items():
+ with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \
+ open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b:
+ cls.f_in[file] = a.read()
+ cls.f_json[file] = json.loads(b.read())
+
+
+ def test_lsb_release_nodata(self):
+ """
+ Test 'lsb_release' with no data
+ """
+ self.assertEqual(parse('', quiet=True), {})
+
+
+ def test_lsb_release_a(self):
+ """
+ Test 'lsb_release -a'
+ """
+ self.assertEqual(
+ parse(self.f_in['lsb_release_a'], quiet=True),
+ self.f_json['lsb_release_a']
+ )
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_mdadm.py b/tests/test_mdadm.py
index f0d048bc..f2a03ef7 100644
--- a/tests/test_mdadm.py
+++ b/tests/test_mdadm.py
@@ -173,7 +173,7 @@ class MyTests(unittest.TestCase):
mdadm_examine_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mdadm-query-detail.json'), 'r', encoding='utf-8') as f:
- mdadm_query_detial_json = json.loads(f.read())
+ mdadm_query_detail_json = json.loads(f.read())
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/mdadm-query-raid0-ok.json'), 'r', encoding='utf-8') as f:
mdadm_query_raid0_ok_json = json.loads(f.read())
@@ -360,7 +360,7 @@ class MyTests(unittest.TestCase):
"""
Test 'mdadm --query --detail'
"""
- self.assertEqual(jc.parsers.mdadm.parse(self.mdadm_query_detail, quiet=True), self.mdadm_query_detial_json)
+ self.assertEqual(jc.parsers.mdadm.parse(self.mdadm_query_detail, quiet=True), self.mdadm_query_detail_json)
def test_mdadm_query_raid0_ok(self):
diff --git a/tests/test_netstat.py b/tests/test_netstat.py
index f8e53985..75531825 100644
--- a/tests/test_netstat.py
+++ b/tests/test_netstat.py
@@ -76,6 +76,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/netstat-old.out'), 'r', encoding='utf-8') as f:
generic_netstat_old = f.read()
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/netstat-no-state.out'), 'r', encoding='utf-8') as f:
+ generic_netstat_no_state = f.read()
+
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/windows/windows-10/netstat.out'), 'r', encoding='utf-8') as f:
windows_netstat = f.read()
@@ -200,6 +203,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/netstat-old.json'), 'r', encoding='utf-8') as f:
generic_netstat_old_json = json.loads(f.read())
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/netstat-no-state.json'), 'r', encoding='utf-8') as f:
+ generic_netstat_no_state_json = json.loads(f.read())
+
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/windows/windows-10/netstat.json'), 'r', encoding='utf-8') as f:
windows_netstat_json = json.loads(f.read())
@@ -389,6 +395,12 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.netstat.parse(self.generic_netstat_old, quiet=True), self.generic_netstat_old_json)
+ def test_netstat_no_state_generic(self):
+ """
+ Test 'netstat' with no state in network output
+ """
+ self.assertEqual(jc.parsers.netstat.parse(self.generic_netstat_no_state, quiet=True), self.generic_netstat_no_state_json)
+
def test_netstat_r_centos_7_7(self):
"""
Test 'netstat -r' on Centos 7.7
diff --git a/tests/test_nsd_control.py b/tests/test_nsd_control.py
new file mode 100644
index 00000000..bf067fa6
--- /dev/null
+++ b/tests/test_nsd_control.py
@@ -0,0 +1,100 @@
+import os
+import unittest
+import json
+from typing import Dict
+from jc.parsers.nsd_control import parse
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+class MyTests(unittest.TestCase):
+ f_in: Dict = {}
+ f_json: Dict = {}
+
+ @classmethod
+ def setUpClass(cls):
+ fixtures = {
+ 'default': (
+ 'fixtures/generic/nsd_control.out',
+ 'fixtures/generic/nsd_control.json'),
+ 'status': (
+ 'fixtures/generic/nsd_control-status.out',
+ 'fixtures/generic/nsd_control-status.json'),
+ 'zonestatus': (
+ 'fixtures/generic/nsd_control-zonestatus.out',
+ 'fixtures/generic/nsd_control-zonestatus.json'),
+ 'print_cookie_secrets': (
+ 'fixtures/generic/nsd_control-cookie_secrets.out',
+ 'fixtures/generic/nsd_control-cookie_secrets.json'),
+ 'print_tsig': (
+ 'fixtures/generic/nsd_control-tsig.out',
+ 'fixtures/generic/nsd_control-tsig.json'),
+ 'stats': (
+ 'fixtures/generic/nsd_control-stats.out',
+ 'fixtures/generic/nsd_control-stats.json')
+ }
+
+ for file, filepaths in fixtures.items():
+ with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \
+ open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b:
+ cls.f_in[file] = a.read()
+ cls.f_json[file] = json.loads(b.read())
+
+
+ def test_nsd_control_default(self):
+ """
+ Test 'nsd-control ' with default output
+ """
+ self.assertEqual(
+ parse(self.f_in['default'], quiet=True),
+ self.f_json['default']
+ )
+
+
+ def test_nsd_control_status(self):
+ """
+ Test 'nsd-control status'
+ """
+ self.assertEqual(
+ parse(self.f_in['status'], quiet=True),
+ self.f_json['status']
+ )
+
+ def test_nsd_control_zonestatus(self):
+ """
+ Test 'nsd-control zonestatus'
+ """
+ self.assertEqual(
+ parse(self.f_in['zonestatus'], quiet=True),
+ self.f_json['zonestatus']
+ )
+
+ def test_nsd_control_cookie_secrets(self):
+ """
+ Test 'nsd-control print_cookie_secrets'
+ """
+ self.assertEqual(
+ parse(self.f_in['print_cookie_secrets'], quiet=True),
+ self.f_json['print_cookie_secrets']
+ )
+
+ def test_nsd_control_tsig(self):
+ """
+ Test 'nsd-control print_tsig'
+ """
+ self.assertEqual(
+ parse(self.f_in['print_tsig'], quiet=True),
+ self.f_json['print_tsig']
+ )
+
+ def test_nsd_control_stats(self):
+ """
+ Test 'nsd-control stats'
+ """
+ self.assertEqual(
+ parse(self.f_in['stats'], quiet=True),
+ self.f_json['stats']
+ )
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_os_release.py b/tests/test_os_release.py
new file mode 100644
index 00000000..f8a5e1fc
--- /dev/null
+++ b/tests/test_os_release.py
@@ -0,0 +1,59 @@
+import os
+import unittest
+import json
+from typing import Dict
+from jc.parsers.os_release import parse
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+class MyTests(unittest.TestCase):
+ f_in: Dict = {}
+ f_json: Dict = {}
+
+ @classmethod
+ def setUpClass(cls):
+ fixtures = {
+ 'os_release_centos': (
+ 'fixtures/generic/os-release-centos',
+ 'fixtures/generic/os-release-centos.json'),
+ 'os_release_ubuntu': (
+ 'fixtures/generic/os-release-ubuntu',
+ 'fixtures/generic/os-release-ubuntu.json')
+ }
+
+ for file, filepaths in fixtures.items():
+ with open(os.path.join(THIS_DIR, filepaths[0]), 'r', encoding='utf-8') as a, \
+ open(os.path.join(THIS_DIR, filepaths[1]), 'r', encoding='utf-8') as b:
+ cls.f_in[file] = a.read()
+ cls.f_json[file] = json.loads(b.read())
+
+
+ def test_os_release_nodata(self):
+ """
+ Test 'os_release' with no data
+ """
+ self.assertEqual(parse('', quiet=True), {})
+
+
+ def test_os_release_centos(self):
+ """
+ Test 'os_release' on Centos
+ """
+ self.assertEqual(
+ parse(self.f_in['os_release_centos'], quiet=True),
+ self.f_json['os_release_centos']
+ )
+
+ def test_os_release_ubuntu(self):
+ """
+ Test 'os_release' on ubuntu
+ """
+ self.assertEqual(
+ parse(self.f_in['os_release_ubuntu'], quiet=True),
+ self.f_json['os_release_ubuntu']
+ )
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_pidstat.py b/tests/test_pidstat.py
index 7544d0f3..ea97cc61 100644
--- a/tests/test_pidstat.py
+++ b/tests/test_pidstat.py
@@ -22,6 +22,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/pidstat-hdlrsuw-2-5.out'), 'r', encoding='utf-8') as f:
centos_7_7_pidstat_hdlrsuw_2_5 = f.read()
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/pidstat-ht.out'), 'r', encoding='utf-8') as f:
+ generic_pidstat_ht = f.read()
+
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/pidstat-hl.json'), 'r', encoding='utf-8') as f:
centos_7_7_pidstat_hl_json = json.loads(f.read())
@@ -32,6 +35,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/pidstat-hdlrsuw-2-5.json'), 'r', encoding='utf-8') as f:
centos_7_7_pidstat_hdlrsuw_2_5_json = json.loads(f.read())
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/pidstat-ht.json'), 'r', encoding='utf-8') as f:
+ generic_pidstat_ht_json = json.loads(f.read())
+
def test_pidstat_nodata(self):
"""
@@ -63,6 +69,12 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.pidstat.parse(self.centos_7_7_pidstat_hdlrsuw_2_5, quiet=True), self.centos_7_7_pidstat_hdlrsuw_2_5_json)
+ def test_pidstat_ht(self):
+ """
+ Test 'pidstat -hT'
+ """
+ self.assertEqual(jc.parsers.pidstat.parse(self.generic_pidstat_ht, quiet=True), self.generic_pidstat_ht_json)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_pidstat_s.py b/tests/test_pidstat_s.py
index fce3156d..a474755f 100644
--- a/tests/test_pidstat_s.py
+++ b/tests/test_pidstat_s.py
@@ -24,6 +24,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/pidstat-hdlrsuw-2-5.out'), 'r', encoding='utf-8') as f:
centos_7_7_pidstat_hdlrsuw_2_5 = f.read()
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/pidstat-ht.out'), 'r', encoding='utf-8') as f:
+ generic_pidstat_ht = f.read()
+
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/pidstat-hl-streaming.json'), 'r', encoding='utf-8') as f:
centos_7_7_pidstat_hl_streaming_json = json.loads(f.read())
@@ -34,6 +37,9 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/pidstat-hdlrsuw-2-5-streaming.json'), 'r', encoding='utf-8') as f:
centos_7_7_pidstat_hdlrsuw_2_5_streaming_json = json.loads(f.read())
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/pidstat-ht-streaming.json'), 'r', encoding='utf-8') as f:
+ generic_pidstat_ht_streaming_json = json.loads(f.read())
+
def test_pidstat_s_nodata(self):
"""
@@ -65,6 +71,12 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(list(jc.parsers.pidstat_s.parse(self.centos_7_7_pidstat_hdlrsuw_2_5.splitlines(), quiet=True)), self.centos_7_7_pidstat_hdlrsuw_2_5_streaming_json)
+ def test_pidstat_s_ht(self):
+ """
+ Test 'pidstat -hT'
+ """
+ self.assertEqual(list(jc.parsers.pidstat_s.parse(self.generic_pidstat_ht.splitlines(), quiet=True)), self.generic_pidstat_ht_streaming_json)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_ping.py b/tests/test_ping.py
index 340437c1..ae56d40c 100644
--- a/tests/test_ping.py
+++ b/tests/test_ping.py
@@ -53,7 +53,7 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ping-missing-hostname.out'), 'r', encoding='utf-8') as f:
centos_7_7_ping_missing_hostname = f.read()
- # ubuntu
+ # ubuntu 18.4
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ping-ip-O.out'), 'r', encoding='utf-8') as f:
ubuntu_18_4_ping_ip_O = f.read()
@@ -81,6 +81,10 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ping6-hostname-O-D-p-s.out'), 'r', encoding='utf-8') as f:
ubuntu_18_4_ping6_hostname_O_D_p_s = f.read()
+ # ubuntu 22.4
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-22.04/ping-dest-unreachable.out'), 'r', encoding='utf-8') as f:
+ ubuntu_22_4_ping_dest_unreachable = f.read()
+
# fedora
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/fedora32/ping-ip-O.out'), 'r', encoding='utf-8') as f:
fedora32_ping_ip_O = f.read()
@@ -257,7 +261,7 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ping-missing-hostname.json'), 'r', encoding='utf-8') as f:
centos_7_7_ping_missing_hostname_json = json.loads(f.read())
- # ubunutu
+ # ubunutu 18.4
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ping-ip-O.json'), 'r', encoding='utf-8') as f:
ubuntu_18_4_ping_ip_O_json = json.loads(f.read())
@@ -285,6 +289,10 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ping6-hostname-O-D-p-s.json'), 'r', encoding='utf-8') as f:
ubuntu_18_4_ping6_hostname_O_D_p_s_json = json.loads(f.read())
+ # ubuntu 22.4
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-22.04/ping-dest-unreachable.json'), 'r', encoding='utf-8') as f:
+ ubuntu_22_4_ping_dest_unreachable_json = json.loads(f.read())
+
# fedora
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/fedora32/ping-ip-O.json'), 'r', encoding='utf-8') as f:
fedora32_ping_ip_O_json = json.loads(f.read())
@@ -555,6 +563,12 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.ping.parse(self.ubuntu_18_4_ping6_hostname_O_D_p_s, quiet=True), self.ubuntu_18_4_ping6_hostname_O_D_p_s_json)
+ def test_ping_dest_unreachable_ubuntu_22_4(self):
+ """
+ Test 'ping' on Ubuntu 22.4 with destination unreachable message
+ """
+ self.assertEqual(jc.parsers.ping.parse(self.ubuntu_22_4_ping_dest_unreachable, quiet=True), self.ubuntu_22_4_ping_dest_unreachable_json)
+
def test_ping_ip_O_fedora32(self):
"""
Test 'ping -O' on fedora32
diff --git a/tests/test_ping_s.py b/tests/test_ping_s.py
index 76a9bc3f..37d6702a 100644
--- a/tests/test_ping_s.py
+++ b/tests/test_ping_s.py
@@ -58,7 +58,7 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ping-missing-hostname.out'), 'r', encoding='utf-8') as f:
centos_7_7_ping_missing_hostname = f.read()
- # ubuntu
+ # ubuntu 18.4
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ping-ip-O.out'), 'r', encoding='utf-8') as f:
ubuntu_18_4_ping_ip_O = f.read()
@@ -86,6 +86,10 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ping6-hostname-O-D-p-s.out'), 'r', encoding='utf-8') as f:
ubuntu_18_4_ping6_hostname_O_D_p_s = f.read()
+ # ubuntu 22.4
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-22.04/ping-dest-unreachable.out'), 'r', encoding='utf-8') as f:
+ ubuntu_22_4_ping_dest_unreachable = f.read()
+
# fedora
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/fedora32/ping-ip-O.out'), 'r', encoding='utf-8') as f:
fedora32_ping_ip_O = f.read()
@@ -252,7 +256,7 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/centos-7.7/ping-missing-hostname-streaming.json'), 'r', encoding='utf-8') as f:
centos_7_7_ping_missing_hostname_json = json.loads(f.read())
- # ubunutu
+ # ubunutu 18.4
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ping-ip-O-streaming.json'), 'r', encoding='utf-8') as f:
ubuntu_18_4_ping_ip_O_streaming_json = json.loads(f.read())
@@ -280,6 +284,10 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-18.04/ping6-hostname-O-D-p-s-streaming.json'), 'r', encoding='utf-8') as f:
ubuntu_18_4_ping6_hostname_O_D_p_s_streaming_json = json.loads(f.read())
+ # ubuntu 22.4
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/ubuntu-22.04/ping-dest-unreachable-streaming.json'), 'r', encoding='utf-8') as f:
+ ubuntu_22_4_ping_dest_unreachable_streaming_json = json.loads(f.read())
+
# fedora
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/fedora32/ping-ip-O-streaming.json'), 'r', encoding='utf-8') as f:
fedora32_ping_ip_O_streaming_json = json.loads(f.read())
@@ -561,6 +569,12 @@ class MyTests(unittest.TestCase):
"""
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_dest_unreachable_ubuntu_22_4(self):
+ """
+ Test 'ping' on Ubuntu 22.4 with destination unreachable message
+ """
+ self.assertEqual(list(jc.parsers.ping_s.parse(self.ubuntu_22_4_ping_dest_unreachable.splitlines(), quiet=True)), [self.ubuntu_22_4_ping_dest_unreachable_streaming_json])
+
def test_ping_s_ip_O_fedora32(self):
"""
Test 'ping -O' on fedora32
diff --git a/tests/test_x509_cert.py b/tests/test_x509_cert.py
index 995260a8..36421d66 100644
--- a/tests/test_x509_cert.py
+++ b/tests/test_x509_cert.py
@@ -27,6 +27,12 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-bad-email.pem'), 'rb') as f:
x509_cert_bad_email = f.read()
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-superfluous-bits.pem'), 'rb') as f:
+ x509_cert_superfluous_bits = f.read()
+
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-negative-serial.pem'), 'rb') as f:
+ x509_cert_negative_serial = f.read()
+
# output
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-ca-cert.json'), 'r', encoding='utf-8') as f:
x509_ca_cert_json = json.loads(f.read())
@@ -46,6 +52,12 @@ class MyTests(unittest.TestCase):
with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-bad-email.json'), 'r', encoding='utf-8') as f:
x509_cert_bad_email_json = json.loads(f.read())
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-cert-superfluous-bits.json'), 'r', encoding='utf-8') as f:
+ x509_cert_superfluous_bits_json = json.loads(f.read())
+
+ with open(os.path.join(THIS_DIR, os.pardir, 'tests/fixtures/generic/x509-negative-serial.json'), 'r', encoding='utf-8') as f:
+ x509_cert_negative_serial_json = json.loads(f.read())
+
def test_x509_cert_nodata(self):
"""
@@ -89,6 +101,18 @@ class MyTests(unittest.TestCase):
"""
self.assertEqual(jc.parsers.x509_cert.parse(self.x509_cert_bad_email, quiet=True), self.x509_cert_bad_email_json)
+ def test_x509_cert_superfluous_bits(self):
+ """
+ Test 'cat x509-cert-superfluous-bits.pem' (PEM file with more bits set for the keyUsage extension than defined by the RFC)
+ """
+ self.assertEqual(jc.parsers.x509_cert.parse(self.x509_cert_superfluous_bits, quiet=True),
+ self.x509_cert_superfluous_bits_json)
+ def test_x509_cert_negative_serial(self):
+ """
+ Test 'cat x509-cert-bad-email.pem' (PEM file with a non-compliant email address)
+ """
+ self.assertEqual(jc.parsers.x509_cert.parse(self.x509_cert_negative_serial, quiet=True), self.x509_cert_negative_serial_json)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_xrandr.py b/tests/test_xrandr.py
index 2866dc32..0c704e88 100644
--- a/tests/test_xrandr.py
+++ b/tests/test_xrandr.py
@@ -21,13 +21,15 @@ from jc.parsers.xrandr import (
Screen,
)
+import pprint
+
class XrandrTests(unittest.TestCase):
def test_xrandr_nodata(self):
"""
Test 'xrandr' with no data
"""
- self.assertEqual(parse('', quiet=True), {})
+ self.assertEqual(parse("", quiet=True), {"screens": []})
def test_regexes(self):
devices = [
@@ -44,7 +46,7 @@ class XrandrTests(unittest.TestCase):
screens = [
"Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 32767 x 32767",
- "Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384"
+ "Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384",
]
for screen in screens:
self.assertIsNotNone(re.match(_screen_pattern, screen))
@@ -63,7 +65,7 @@ class XrandrTests(unittest.TestCase):
if match:
rest = match.groupdict()["rest"]
self.assertIsNotNone(re.match(_frequencies_pattern, rest))
-
+
edid_lines = [
" EDID: ",
" 00ffffffffffff000469d41901010101 ",
@@ -73,7 +75,7 @@ class XrandrTests(unittest.TestCase):
" 360098ff1000001c000000fd00374b1e ",
" 530f000a202020202020000000fc0041 ",
" 535553205657313933530a20000000ff ",
- " 0037384c383032313130370a20200077 "
+ " 0037384c383032313130370a20200077 ",
]
for i in range(len(edid_lines)):
@@ -104,7 +106,9 @@ class XrandrTests(unittest.TestCase):
for k, v in expected.items():
self.assertEqual(v, actual[k], f"screens regex failed on {k}")
- sample = "Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384"
+ sample = (
+ "Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384"
+ )
actual = _parse_screen([sample])
if actual:
self.assertEqual(320, actual["minimum_width"])
@@ -141,9 +145,7 @@ class XrandrTests(unittest.TestCase):
device = _parse_device(extended_sample)
if device:
- self.assertEqual(
- 59.94, device["associated_modes"][12]["frequencies"][4]["frequency"]
- )
+ self.assertEqual(59.94, device["modes"][12]["frequencies"][4]["frequency"])
def test_device_with_reflect(self):
sample = "VGA-1 connected primary 1920x1080+0+0 left X and Y axis (normal left inverted right x axis y axis) 310mm x 170mm"
@@ -195,67 +197,49 @@ class XrandrTests(unittest.TestCase):
self.assertEqual(True, actual["is_high_resolution"])
self.assertEqual(50.0, actual["frequencies"][1]["frequency"])
- def test_complete(self):
+ def test_complete_1(self):
self.maxDiff = None
with open("tests/fixtures/generic/xrandr.out", "r") as f:
txt = f.read()
actual = parse(txt, quiet=True)
self.assertEqual(1, len(actual["screens"]))
- self.assertEqual(4, len(actual["unassociated_devices"]))
- self.assertEqual(
- 18, len(actual["screens"][0]["associated_device"]["associated_modes"])
- )
+ self.assertEqual(18, len(actual["screens"][0]["devices"][0]["modes"]))
+ def test_complete_2(self):
with open("tests/fixtures/generic/xrandr_2.out", "r") as f:
txt = f.read()
actual = parse(txt, quiet=True)
self.assertEqual(1, len(actual["screens"]))
- self.assertEqual(3, len(actual["unassociated_devices"]))
+ self.assertEqual(38, len(actual["screens"][0]["devices"][0]["modes"]))
+
+ def test_complete_3(self):
+ with open("tests/fixtures/generic/xrandr_3.out", "r") as f:
+ txt = f.read()
+ actual = parse(txt, quiet=True)
+
+ self.assertEqual(1, len(actual["screens"]))
self.assertEqual(
- 38, len(actual["screens"][0]["associated_device"]["associated_modes"])
+ 2,
+ len(actual["screens"][0]["devices"]),
)
+ def test_complete_4(self):
with open("tests/fixtures/generic/xrandr_simple.out", "r") as f:
txt = f.read()
actual = parse(txt, quiet=True)
self.assertEqual(1, len(actual["screens"]))
- self.assertEqual(0, len(actual["unassociated_devices"]))
- self.assertEqual(
- 2, len(actual["screens"][0]["associated_device"]["associated_modes"])
- )
+ self.assertEqual(2, len(actual["screens"][0]["devices"][0]["modes"]))
+ def test_complete_5(self):
with open("tests/fixtures/generic/xrandr_properties.out", "r") as f:
txt = f.read()
actual = parse(txt, quiet=True)
self.assertEqual(1, len(actual["screens"]))
- self.assertEqual(3, len(actual["unassociated_devices"]))
- self.assertEqual(
- 29, len(actual["screens"][0]["associated_device"]["associated_modes"])
- )
-
- def test_infinite_loop_fix(self):
- with open("tests/fixtures/generic/xrandr_fix_spaces.out", "r") as f:
- txt = f.read()
- actual = parse(txt, quiet=True)
-
- with open("tests/fixtures/generic/xrandr_fix_spaces.json", "r") as f:
- json_dict = json.loads(f.read())
-
- self.assertEqual(actual, json_dict)
-
- def test_is_current_fix(self):
- with open("tests/fixtures/generic/xrandr_is_current_fix.out", "r") as f:
- txt = f.read()
- actual = parse(txt, quiet=True)
-
- with open("tests/fixtures/generic/xrandr_is_current_fix.json", "r") as f:
- json_dict = json.loads(f.read())
-
- self.assertEqual(actual, json_dict)
+ self.assertEqual(29, len(actual["screens"][0]["devices"][0]["modes"]))
def test_model(self):
asus_edid = [
@@ -267,7 +251,7 @@ class XrandrTests(unittest.TestCase):
" 360098ff1000001c000000fd00374b1e",
" 530f000a202020202020000000fc0041",
" 535553205657313933530a20000000ff",
- " 0037384c383032313130370a20200077"
+ " 0037384c383032313130370a20200077",
]
asus_edid.reverse()
@@ -293,8 +277,8 @@ class XrandrTests(unittest.TestCase):
" 250058c2100000190000000f00000000",
" 000000000025d9066a00000000fe0053",
" 414d53554e470a204ca34154000000fe",
- " 004c544e313536415432343430310018"
- ]
+ " 004c544e313536415432343430310018",
+ ]
generic_edid.reverse()
expected = {
@@ -314,5 +298,6 @@ class XrandrTests(unittest.TestCase):
actual: Optional[Model] = _parse_model(empty_edid)
self.assertIsNone(actual)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
unittest.main()