diff --git a/Makefile b/Makefile index 0e399b4..5b72216 100644 --- a/Makefile +++ b/Makefile @@ -62,10 +62,11 @@ help: # Tests ######################################################################## -.PHONY: check cond expr loop macros syntax expand +.PHONY: check jqt format cond expr loop macros syntax expand csv yaml -check: expand jqt +check: expand jqt format jqt: cond expr loop macros syntax +format: csv yaml define TestJQT # Run one example @@ -83,6 +84,8 @@ $(1)-%: $(1)-%.jqt ; $(1): $(sort $(subst tests/,,$(wildcard tests/$(1)-[0-9][0-9].jqt))) endef +$(foreach t,cond expr loop macros syntax,$(eval $(call TestJQT,$(t)))) + define TestGPP # Run one example $(2)-%.$(1): @@ -96,10 +99,21 @@ $(2): $(sort $(subst tests/,,$(wildcard tests/$(2)-[0-9][0-9].$(1)))) endef $(eval $(call TestGPP,jqt,expand)) -$(eval $(call TestJQT,cond)) -$(eval $(call TestJQT,expr)) -$(eval $(call TestJQT,loop)) -$(eval $(call TestJQT,macros)) -$(eval $(call TestJQT,syntax)) + +define TestFileFormat +# Run one example +$(1)-%.sh: + echo "==> $$(basename $$@)" + $(SHELL) tests/$$@ +# Run one example named without file suffix +$(1)-%: $(1)-%.sh ; +# Run all tests +$(1): $(sort $(subst tests/,,$(wildcard tests/$(1)-[0-9][0-9].sh))) +# Check output of all filters is empty for empty input + test -z "$$$$(for f in bin/$(1)2* bin/*2$(1); do echo | $$$$f; done)" \ + || { echo 1>&2 'EMPTY-FAILED'; false; } +endef + +$(foreach t,csv yaml,$(eval $(call TestFileFormat,$(t)))) # vim:ai:sw=8:ts=8:noet:syntax=make diff --git a/bin/cq b/bin/cq new file mode 100755 index 0000000..a59af30 --- /dev/null +++ b/bin/cq @@ -0,0 +1,114 @@ +#!/bin/bash + +# +# Wraps jq to be able to process CSV +# + +# Options +set -o errexit -o noglob -o nounset -o pipefail +shopt -s expand_aliases + +# Script name +declare -r SELF=${0##*/} + +# Format conversors +alias c2j=${0%$SELF}csv2json +alias j2c=${0%$SELF}json2csv +alias j2y=${0%$SELF}json2yaml + +# Show help +function help { + cat < [file] + + ${SELF} is a wrapper to jq for processing CSV input, applying the given + filter to it CSV text input and producing the filter's results as + CSV or JSON on standard output. + + The options available are ${SELF} specific and also from jq. The ${SELF} + options are: + -h Show this help + -C Output using CSV format (default) + -J Output using JSON format + -Y Output using YAML format + -V Output the jq version + + Some of the jq options include: + -e set the exit status code based on the output + -f Read filter from the file f + -s read (slurp) all inputs into an array; apply filter to it + -S sort keys of objects on output + --arg a v set variable \$a to value v + --argjson a v set variable \$a to JSON value v + --slurpfile a f set variable \$a to an array of values read from f + Not all jq options have sense using ${SELF}. + + For more advanced filters see the jq(1) manpage and + https://stedolan.github.io/jq +EOF + exit $(( $# == 0 )) +} + +# Entry point +function main { + local -i json=0 yaml=0 + + local opt + while getopts :hJKVY-: opt; do + case $opt in + h) help ;; + C) ;; + J) json=1 ;; + Y) yaml=1 ;; + V) exec jq --version ;; + -) case $OPTARG in + help) help ;; + CSV|csv) ;; + JSON|json) json=1 ;; + YAML|yaml) yaml=1 ;; + *) OPTIND=$((OPTIND-1)) + break ;; # assume jq option + esac + ;; + ?) OPTIND=$((OPTIND-1)) + break ;; # assume jq option + esac + done + + shift $((OPTIND-1)) + (( $# > 0 )) || help + [[ $1 == '--version' ]] && exec jq --version + + # Is stdin a TTY? + if [[ -t 0 ]]; then + if (( $# >= 2 )); then + # Is the last parameter a regular file? + local last=${!#} + if [[ -f $last ]]; then + # reopen stdin + exec 0< "$last" + # remove last parameter + set -- "${@:1:$(($#-1))}" + fi + fi + fi + + # Wrap jq + if (( json )); then + # Preserve JSON output + c2j | jq "$@" + elif (( yaml )); then + c2j | jq "$@" | j2y + else + c2j | jq "$@" | j2c + fi + + # Exit status is that of the last command executed. + exit +} + +# Call main +main "$@" + +# vim:ai:sw=4:ts=4:et:syntax=sh diff --git a/bin/yq b/bin/yq new file mode 100755 index 0000000..9741246 --- /dev/null +++ b/bin/yq @@ -0,0 +1,114 @@ +#!/bin/bash + +# +# Wraps jq to be able to process YAML +# + +# Options +set -o errexit -o noglob -o nounset -o pipefail +shopt -s expand_aliases + +# Script name +declare -r SELF=${0##*/} + +# Format conversors +alias y2j=${0%$SELF}yaml2json +alias j2y=${0%$SELF}json2yaml +alias j2c=${0%$SELF}json2csv + +# Show help +function help { + cat < [file] + + ${SELF} is a wrapper to jq for processing YAML input, applying the given + filter to it YAML text input and producing the filter's results as + YAML or JSON on standard output. + + The options available are ${SELF} specific and also from jq. The ${SELF} + options are: + -h Show this help + -J Output using JSON format + -C Output using CSV format + -Y Output using YAML format (default) + -V Output the jq version + + Some of the jq options include: + -e set the exit status code based on the output + -f Read filter from the file f + -s read (slurp) all inputs into an array; apply filter to it + -S sort keys of objects on output + --arg a v set variable \$a to value v + --argjson a v set variable \$a to JSON value v + --slurpfile a f set variable \$a to an array of values read from f + Not all jq options have sense using ${SELF}. + + For more advanced filters see the jq(1) manpage and + https://stedolan.github.io/jq +EOF + exit $(( $# == 0 )) +} + +# Entry point +function main { + local -i json=0 csv=0 + + local opt + while getopts :hCJKVY-: opt; do + case $opt in + h) help ;; + C) csv=1 ;; + J) json=1 ;; + Y) ;; + V) exec jq --version ;; + -) case $OPTARG in + help) help ;; + CSV|csv) csv=1 ;; + JSON|json) json=1 ;; + YAML|yaml) ;; + *) OPTIND=$((OPTIND-1)) + break ;; # assume jq option + esac + ;; + ?) OPTIND=$((OPTIND-1)) + break ;; # assume jq option + esac + done + + shift $((OPTIND-1)) + (( $# > 0 )) || help + [[ $1 == '--version' ]] && exec jq --version + + # Is stdin a TTY? + if [[ -t 0 ]]; then + if (( $# >= 2 )); then + # Is the last parameter a regular file? + local last=${!#} + if [[ -f $last ]]; then + # reopen stdin + exec 0< "$last" + # remove last parameter + set -- "${@:1:$(($#-1))}" + fi + fi + fi + + # Wrap jq + if (( json )); then + # Preserve JSON output + y2j | jq "$@" + elif (( csv )); then + y2j | jq "$@" | j2c + else + y2j | jq "$@" | j2y + fi + + # Exit status is that of the last command executed. + exit +} + +# Call main +main "$@" + +# vim:ai:sw=4:ts=4:et:syntax=sh diff --git a/docs/Makefile b/docs/Makefile index 165c7a8..794480a 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -59,17 +59,11 @@ CONTENT := ./content STRUCTURE := ./structure PRESENTATION := ./presentation -# Global objects available in jq scripts: -# .body predefined by jqt -# .front predefined by jqt -# .site defined in the jqt call -# .snippets defined in the jqt call - -# The template engine +# The template engine (.site and .snippets defined in the jqt call) JQT := jqt \ -I$(STRUCTURE) \ -I$(CONTENT) \ - -isite \ + -ifilters \ -msite:$(CACHE)/site.json \ -msnippets:$(CACHE)/snippets.json \ --toc-depth=3 \ @@ -92,64 +86,69 @@ COMMON := \ $(STRUCTURE)/head.html \ $(STRUCTURE)/footer.html \ $(CONTENT)/LINKS.md \ - site.m \ - site.jq \ + filters.jq \ + macros.m \ # Files to "build" -TARGETS := \ - $(DESTINATION)/README.md \ - $(DESTINATION)/document.html \ - $(DESTINATION)/engine.html \ - $(DESTINATION)/index.html \ - $(DESTINATION)/metadata.html \ - $(DESTINATION)/template.html \ - $(DESTINATION)/jqt.css \ +ASSETS := README.md jqt.css +PAGES := engine document metadata template +TARGETS := $(foreach f,$(ASSETS) $(foreach p,index $(PAGES),$(p).html),$(DESTINATION)/$(f)) ######################################################################## # Rules ######################################################################## +# Main +all: $(TARGETS) + test -f /etc/xml/xhtml1-dtds.xml \ + && xmllint --noout --valid $(DESTINATION)/*.html + # Directories $(CACHE) $(DESTINATION): mkdir $@ >/dev/null 2>&1 || true -# Assets -$(DESTINATION)/README.md: README.md | $(DESTINATION) - cp $< $@ - -# Derived files -$(CACHE)/site.json: site.yaml | $(CACHE) +# Cached files +$(CACHE)/site.json: site.yaml \ +| $(CACHE) yaml2json < $< > $@ $(CACHE)/snippets.pandoc: private id=^\([a-zA-Z_-]\+\) -$(CACHE)/snippets.pandoc: $(CONTENT)/snippets.yaml | $(CACHE) +$(CACHE)/snippets.pandoc: $(CONTENT)/snippets.yaml \ +| $(CACHE) sed '/$(id): *[>|]/{s/$(id):.*/\1: >\n $$\1$$/;b;};/$(id): *[^#]/{s/$(id):.*/\1: $$\1$$/;b;};d;' \ < $< > $@ -$(CACHE)/snippets.json: $(CONTENT)/snippets.yaml $(CACHE)/snippets.pandoc | $(CACHE) +$(CACHE)/snippets.json: $(CONTENT)/snippets.yaml $(CACHE)/snippets.pandoc \ +| $(CACHE) pandoc --from markdown --to html --template=$(CACHE)/snippets.pandoc $< \ | yaml2json > $@ -# Pages -$(DESTINATION)/index.html: $(CONTENT)/home.md $(COMMON) | $(DESTINATION) +# Target files +$(DESTINATION)/README.md: README.md \ +| $(DESTINATION) + $(info ==> $@) + cp $< $@ + +$(DESTINATION)/index.html: $(CONTENT)/home.md $(COMMON) \ +| $(DESTINATION) + $(info ==> $@) $(JQT) -d $< $(STRUCTURE)/default.html > $@ -define Page -$(DESTINATION)/$(1).html: $(CONTENT)/$(1).md $(STRUCTURE)/page.html $(COMMON) $(CONTENT)/FLOW.md | $(DESTINATION) - $$(JQT) -d $$< $(STRUCTURE)/page.html > $$@ +$(DESTINATION)/engine.html: $(CONTENT)/FLOW.md + +define Target +$(DESTINATION)/$(1).html: $(CONTENT)/$(1).md $(STRUCTURE)/$(2).html $(COMMON) \ +| $(DESTINATION) + $$(info ==> $$@) + $$(JQT) -d $$< $(STRUCTURE)/$(2).html > $$@ endef -PAGES := engine document metadata template -$(foreach page,$(PAGES),$(eval $(call Page,$(page)))) +$(foreach p,$(PAGES),$(eval $(call Target,$(p),page))) -# CSS $(DESTINATION)/jqt.css: $(PRESENTATION)/jqt.css $(PRESENTATION)/github.css + $(info ==> $@) $(MPCSS) $< | $(CSSMIN) > $@ -# Main -all: $(TARGETS) - @xmllint --noout --valid $(DESTINATION)/*.html - ######################################################################## # Utilities ######################################################################## @@ -164,4 +163,15 @@ clobber: build: clean all +# Show targets +.PHONY: help +help: + echo 'Targets:'; \ + $(MAKE) --print-data-base --just-print 2>&1 \ + | grep -v '^[mM]akefile' \ + | awk '/^[^ \t.%][-A-Za-z0-9_]*:/ { print $$1 }' \ + | sort --unique \ + | sed 's/:\+$$//' \ + | pr --omit-pagination --indent=4 --width=80 --columns=4 + # vim:ai:sw=8:ts=8:noet:fileencoding=utf8:syntax=make diff --git a/docs/content/document.md b/docs/content/document.md index 40cedf2..29fe80f 100644 --- a/docs/content/document.md +++ b/docs/content/document.md @@ -3,7 +3,7 @@ title: Content documents updated: "2016-08-13T07:48:26Z" --- -<%include "site.m">& +<%include "macros.m">& <%include "LINKS.md">& ## Document structure @@ -63,20 +63,21 @@ Fenced code blocks with tildes (~~~) or backticks (```) When running `jqt` several long options are forwarded to `pandoc`: ``` ---base-header-level=NUMBER --katex-stylesheet ---bibliography=FILE --latexmathml[=URL] ---citation-abbreviations=FILE --mathjax[=URL] ---columns=NUMBER --mathml[=URL] ---csl=FILE --mimetex[=URL] ---email-obfuscation=none|javascript|references --no-highlight ---file-scope --normalize ---gladtex --number-offset=NUMBER[,NUMBER,...] ---highlight-style=STYLE --number-sections ---html-q-tags --preserve-tabs ---id-prefix=STRING --section-divs ---indented-code-classes=CLASSES --tab-stop=NUMBER ---jsmath[=URL] --webtex[=URL] ---katex[=URL] --wrap=[auto|none|preserve] + --base-header-level=NUMBER --latexmathml[=URL] + --bibliography=FILE --mathjax[=URL] + --citation-abbreviations=FILE --mathml[=URL] + --columns=NUMBER --mimetex[=URL] + --csl=FILE --no-highlight + --email-obfuscation=none|javascript|references --normalize + --file-scope --number-offset=NUMBER[,NUMBER,...] + --gladtex --number-sections + --highlight-style=STYLE --preserve-tabs + --html-q-tags --section-divs + --id-prefix=STRING --tab-stop=NUMBER + --indented-code-classes=CLASSES --toc-depth=NUMBER + --jsmath[=URL] --webtex[=URL] + --katex[=URL] --wrap=[auto|none|preserve] + --katex-stylesheet ``` <# diff --git a/docs/content/engine.md b/docs/content/engine.md index ea3346e..6e16651 100644 --- a/docs/content/engine.md +++ b/docs/content/engine.md @@ -3,7 +3,7 @@ title: Operating the engine updated: "2016-08-13T07:48:26Z" --- -<%include "site.m">& +<%include "macros.m">& <%include "LINKS.md">& ## General operation @@ -76,12 +76,12 @@ for included and imported modules. -M NAME:FILE -: Add a *FILE* in JSON or YAML format to the input metadata at the top level +: Add a *FILE* in YAML or JSON format to the input metadata at the top level (*NAME* is ignored but must be present and unique). -m NAME:FILE -: Add a *FILE* in JSON or YAML format to the input metadata as a value of object *NAME*. +: Add a *FILE* in YAML or JSON format to the input metadata as a value of object *NAME*. #### Debugging options @@ -128,7 +128,7 @@ MarkDown). ## jq templates The jq template language will be called jqt. - The tools used in theimplementation of jqt are: + The tools used in the implementation of jqt are: ``` -H diff --git a/docs/content/home.md b/docs/content/home.md index 73b4e3b..95ecfe7 100644 --- a/docs/content/home.md +++ b/docs/content/home.md @@ -2,7 +2,7 @@ <%include "site.yaml"> updated: "2016-08-13T07:48:26Z" --- -<%include "site.m">& +<%include "macros.m">& <%include "LINKS.md">& Could be [_jq_][JQ] the basis for a web template engine? @@ -42,7 +42,7 @@ To write _jq_ scripts using strings with interpolations is not the idea we have for a template language. We need some syntactic sugar, and this is provided to you by _jqt_. You write templates in a very fashionable style, the templates are translated into a _jq_ script and then `jq` is feed with the created -script and some metadata and content in JSON or YAML format… and the magic is done! +script and some metadata and content in YAML or JSON format… and the magic is done! ### Syntactic sugar diff --git a/docs/content/metadata.md b/docs/content/metadata.md index 79130bd..55423de 100644 --- a/docs/content/metadata.md +++ b/docs/content/metadata.md @@ -3,7 +3,7 @@ title: Data model updated: "2016-08-13T07:48:26Z" --- -<%include "site.m">& +<%include "macros.m">& <%include "LINKS.md">& Metadata in YAML and JSON formats @@ -12,6 +12,57 @@ Metadata in YAML and JSON formats ### Preprocessing +## Other utilities + +When preparing metadata sometimes you need to mix files in several formats, or you +want to apply to YAML input queries in the _jq_ style. + +### Format conversion + +To make easy integrate metadata from several sources _jqt_ comes with the +following utilities to convert between CSV, JSON and YAML formats: + +* `csv2json` +* `csv2yaml` +* `json2csv` +* `json2yaml` +* `yaml2csv` +* `yaml2json` + +The utilities are filters that read standard input or a file passed as an +argument and write to standard output. + +### Querying YAML and CSV + +Also, sometimes you want to apply queries in the _jq_ style to CSV or YAML files. +As a wrappers to `jq` you have the following utilities shipped with _jqt_: + +* `cq` +* `yq` + +These utilities imitate at maximum the `jq` command line interface, for example +not requiring redirection of input: + +``` +$ yq '.store.book[2]' tests/data/store.yaml +--- +author: Herman Melville +category: fiction +isbn: 0-553-21311-3 +price: 8.99 +title: Moby Dick +... +``` + +You can also ask for JSON output: + +``` +$ yq --json -c '.store.book[2]' tests/data/store.yaml +{"category":"fiction","price":8.99,"author":"Herman Melville",... +``` + +Read the output of `yq --help` for more information. + <# vim:ts=4:sw=4:ai:et:fileencoding=utf8:syntax=markdown #> diff --git a/docs/content/template.md b/docs/content/template.md index 9672437..a6b76f3 100644 --- a/docs/content/template.md +++ b/docs/content/template.md @@ -3,7 +3,7 @@ title: Templates syntax updated: "2016-08-13T07:48:26Z" --- -<%include "site.m">& +<%include "macros.m">& <%include "LINKS.md">& ### Main _jqt_ features diff --git a/docs/site.jq b/docs/filters.jq similarity index 100% rename from docs/site.jq rename to docs/filters.jq diff --git a/docs/site.m b/docs/macros.m similarity index 100% rename from docs/site.m rename to docs/macros.m diff --git a/docs/structure/default.html b/docs/structure/default.html index 2b9da94..d64bc7b 100644 --- a/docs/structure/default.html +++ b/docs/structure/default.html @@ -1,5 +1,5 @@ <# Default layout #> -<%include "site.m">& +<%include "macros.m">& diff --git a/tests/csv-01.sh b/tests/csv-01.sh new file mode 100644 index 0000000..b68f9de --- /dev/null +++ b/tests/csv-01.sh @@ -0,0 +1,20 @@ +# data/au.json == (j2c data/au.csv | c2j) + +set -o errexit -o pipefail -o nounset + +cd $(dirname $0) + +# Conversions +C2J=../bin/csv2json +J2C=../bin/json2csv + +# Slurp two files into variable +jq --null-input --raw-output \ + --slurpfile j1 data/au.json \ + --slurpfile j2 <(${J2C} data/au.json | ${C2J}) \ + '$j1 == $j2' | grep -q true + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh + diff --git a/tests/csv-03.sh b/tests/csv-03.sh new file mode 100644 index 0000000..f0be613 --- /dev/null +++ b/tests/csv-03.sh @@ -0,0 +1,17 @@ +# jq q JSON == cq q YAML + +set -o errexit -o pipefail -o nounset + +cd $(dirname $0) + +# Conversions +CQ=../bin/cq +J2C=../bin/json2csv + +# Same result +diff <(jq -s '.[1]' data/au.json | ${J2C}) \ + <(${CQ} -s '.[1]' data/au.csv) + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh diff --git a/tests/csv-04.sh b/tests/csv-04.sh new file mode 100644 index 0000000..a7ffe57 --- /dev/null +++ b/tests/csv-04.sh @@ -0,0 +1,16 @@ +# cq q YAML == s + +set -o errexit -o pipefail -o nounset + +cd $(dirname $0) + +# Query +CQ=../bin/cq + +# Extract string +(( $(${CQ} -J -r 'select(.city == "Hamel").post' data/au.csv) == 6215 )) + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh + diff --git a/tests/data/au.csv b/tests/data/au.csv new file mode 100644 index 0000000..a637732 --- /dev/null +++ b/tests/data/au.csv @@ -0,0 +1,11 @@ +"first_name","last_name","company_name","address","city","state","post","phone1","phone2","email","web" +"Ena","Desjardiws","Selsor, Robert J Esq","60562 Ky Rt 321","Bendick Murrell","NS",2803,"02-5226-9402","0415-961-606","ena_desjardiws@desjardiws.com.au","http://www.selsorrobertjesq.com.au" +"Gerardo","Woodka","Morris Downing & Sherred","69206 Jackson Ave","Talmalmo","NS",2640,"02-6044-4682","0443-795-912","gerardo_woodka@hotmail.com","http://www.morrisdowningsherred.com.au" +"Idella","Scotland","Artesian Ice & Cold Storage Co","373 Lafayette St","Cartmeticup","WA",6316,"08-7868-1355","0451-966-921","idella@hotmail.com","http://www.artesianicecoldstorageco.com.au" +"Mariko","Stayer","Inabinet, Macre Esq","534 Schoenborn St #51","Hamel","WA",6215,"08-5558-9019","0427-885-282","mariko_stayer@hotmail.com","http://www.inabinetmacreesq.com.au" +"Mayra","Bena","Buelt, David L Esq","808 Glen Cove Ave","Lane Cove","NS",1595,"02-1455-6085","0453-666-885","mayra.bena@gmail.com","http://www.bueltdavidlesq.com.au" +"Rebbecca","Didio","Brandt, Jonathan F Esq","171 E 24th St","Leith","TA",7315,"03-8174-9123","0458-665-290","rebbecca.didio@didio.com.au","http://www.brandtjonathanfesq.com.au" +"Sherill","Klar","Midway Hotel","87 Sylvan Ave","Nyamup","WA",6258,"08-6522-8931","0427-991-688","sklar@hotmail.com","http://www.midwayhotel.com.au" +"Stevie","Hallo","Landrum Temporary Services","22222 Acoma St","Proston","QL",4613,"07-9997-3366","0497-622-620","stevie.hallo@hotmail.com","http://www.landrumtemporaryservices.com.au" +"Theron","Jarding","Prentiss, Paul F Esq","8839 Ventura Blvd","Blanchetown","SA",5357,"08-6890-4661","0461-862-457","tjarding@hotmail.com","http://www.prentisspaulfesq.com.au" +"Vince","Siena","Vincent J Petti & Co","70 S 18th Pl","Purrawunda","QL",4356,"07-3184-9989","0411-732-965","vince_siena@yahoo.com","http://www.vincentjpettico.com.au" diff --git a/tests/data/au.json b/tests/data/au.json new file mode 100644 index 0000000..368f051 --- /dev/null +++ b/tests/data/au.json @@ -0,0 +1,130 @@ +{ + "city": "Bendick Murrell", + "first_name": "Ena", + "last_name": "Desjardiws", + "web": "http://www.selsorrobertjesq.com.au", + "phone2": "0415-961-606", + "phone1": "02-5226-9402", + "state": "NS", + "company_name": "Selsor, Robert J Esq", + "address": "60562 Ky Rt 321", + "post": "2803", + "email": "ena_desjardiws@desjardiws.com.au" +} +{ + "city": "Talmalmo", + "first_name": "Gerardo", + "last_name": "Woodka", + "web": "http://www.morrisdowningsherred.com.au", + "phone2": "0443-795-912", + "phone1": "02-6044-4682", + "state": "NS", + "company_name": "Morris Downing & Sherred", + "address": "69206 Jackson Ave", + "post": "2640", + "email": "gerardo_woodka@hotmail.com" +} +{ + "city": "Cartmeticup", + "first_name": "Idella", + "last_name": "Scotland", + "web": "http://www.artesianicecoldstorageco.com.au", + "phone2": "0451-966-921", + "phone1": "08-7868-1355", + "state": "WA", + "company_name": "Artesian Ice & Cold Storage Co", + "address": "373 Lafayette St", + "post": "6316", + "email": "idella@hotmail.com" +} +{ + "city": "Hamel", + "first_name": "Mariko", + "last_name": "Stayer", + "web": "http://www.inabinetmacreesq.com.au", + "phone2": "0427-885-282", + "phone1": "08-5558-9019", + "state": "WA", + "company_name": "Inabinet, Macre Esq", + "address": "534 Schoenborn St #51", + "post": "6215", + "email": "mariko_stayer@hotmail.com" +} +{ + "city": "Lane Cove", + "first_name": "Mayra", + "last_name": "Bena", + "web": "http://www.bueltdavidlesq.com.au", + "phone2": "0453-666-885", + "phone1": "02-1455-6085", + "state": "NS", + "company_name": "Buelt, David L Esq", + "address": "808 Glen Cove Ave", + "post": "1595", + "email": "mayra.bena@gmail.com" +} +{ + "city": "Leith", + "first_name": "Rebbecca", + "last_name": "Didio", + "web": "http://www.brandtjonathanfesq.com.au", + "phone2": "0458-665-290", + "phone1": "03-8174-9123", + "state": "TA", + "company_name": "Brandt, Jonathan F Esq", + "address": "171 E 24th St", + "post": "7315", + "email": "rebbecca.didio@didio.com.au" +} +{ + "city": "Nyamup", + "first_name": "Sherill", + "last_name": "Klar", + "web": "http://www.midwayhotel.com.au", + "phone2": "0427-991-688", + "phone1": "08-6522-8931", + "state": "WA", + "company_name": "Midway Hotel", + "address": "87 Sylvan Ave", + "post": "6258", + "email": "sklar@hotmail.com" +} +{ + "city": "Proston", + "first_name": "Stevie", + "last_name": "Hallo", + "web": "http://www.landrumtemporaryservices.com.au", + "phone2": "0497-622-620", + "phone1": "07-9997-3366", + "state": "QL", + "company_name": "Landrum Temporary Services", + "address": "22222 Acoma St", + "post": "4613", + "email": "stevie.hallo@hotmail.com" +} +{ + "city": "Blanchetown", + "first_name": "Theron", + "last_name": "Jarding", + "web": "http://www.prentisspaulfesq.com.au", + "phone2": "0461-862-457", + "phone1": "08-6890-4661", + "state": "SA", + "company_name": "Prentiss, Paul F Esq", + "address": "8839 Ventura Blvd", + "post": "5357", + "email": "tjarding@hotmail.com" +} +{ + "city": "Purrawunda", + "first_name": "Vince", + "last_name": "Siena", + "web": "http://www.vincentjpettico.com.au", + "phone2": "0411-732-965", + "phone1": "07-3184-9989", + "state": "QL", + "company_name": "Vincent J Petti & Co", + "address": "70 S 18th Pl", + "post": "4356", + "email": "vince_siena@yahoo.com" +} diff --git a/tests/data/hardware.json b/tests/data/hardware.json new file mode 100644 index 0000000..01ef8d4 --- /dev/null +++ b/tests/data/hardware.json @@ -0,0 +1,1023 @@ +{ + "id" : "wks4.escoladeltreball.org", + "class" : "system", + "claimed" : true, + "handle" : "DMI:0001", + "description" : "Desktop Computer", + "product" : "To be filled by O.E.M. (To be filled by O.E.M.)", + "vendor" : "Gigabyte Technology Co., Ltd.", + "version" : "To be filled by O.E.M.", + "serial" : "To be filled by O.E.M.", + "width" : 4294967295, + "configuration" : { + "boot" : "normal", + "chassis" : "desktop", + "family" : "To be filled by O.E.M.", + "sku" : "To be filled by O.E.M.", + "uuid" : "7402D403-3504-2005-AA06-030700080009" + }, + "capabilities" : { + "smbios-2.7" : "SMBIOS version 2.7", + "dmi-2.7" : "DMI version 2.7", + "smp" : "Symmetric Multi-Processing", + "vsyscall32" : "32-bit processes" + }, + "children" : [ + { + "id" : "core", + "class" : "bus", + "claimed" : true, + "handle" : "DMI:0002", + "description" : "Motherboard", + "product" : "H61M-S2PV REV 2.2", + "vendor" : "Gigabyte Technology Co., Ltd.", + "physid" : "0", + "version" : "x.x", + "serial" : "To be filled by O.E.M.", + "slot" : "To be filled by O.E.M.", + "children" : [ + { + "id" : "firmware", + "class" : "memory", + "claimed" : true, + "description" : "BIOS", + "vendor" : "American Megatrends Inc.", + "physid" : "0", + "version" : "FB", + "date" : "02/25/2013", + "units" : "bytes", + "size" : 65536, + "capacity" : 4128768, + "capabilities" : { + "pci" : "PCI bus", + "upgrade" : "BIOS EEPROM can be upgraded", + "shadowing" : "BIOS shadowing", + "cdboot" : "Booting from CD-ROM/DVD", + "bootselect" : "Selectable boot path", + "socketedrom" : "BIOS ROM is socketed", + "edd" : "Enhanced Disk Drive extensions", + "int13floppy1200" : "5.25\" 1.2MB floppy", + "int13floppy720" : "3.5\" 720KB floppy", + "int13floppy2880" : "3.5\" 2.88MB floppy", + "int5printscreen" : "Print Screen key", + "int9keyboard" : "i8042 keyboard controller", + "int14serial" : "INT14 serial line control", + "int17printer" : "INT17 printer control", + "acpi" : "ACPI", + "usb" : "USB legacy emulation", + "biosbootspecification" : "BIOS boot specification", + "uefi" : "UEFI specification is supported" + } + }, + { + "id" : "cache:0", + "class" : "memory", + "claimed" : true, + "handle" : "DMI:0004", + "description" : "L1 cache", + "physid" : "4", + "slot" : "CPU Internal L1", + "units" : "bytes", + "size" : 131072, + "capacity" : 131072, + "configuration" : { + "level" : "1" + }, + "capabilities" : { + "internal" : "Internal", + "write-through" : "Write-trough" + } + }, + { + "id" : "cache:1", + "class" : "memory", + "claimed" : true, + "handle" : "DMI:0005", + "description" : "L2 cache", + "physid" : "5", + "slot" : "CPU Internal L2", + "units" : "bytes", + "size" : 1048576, + "capacity" : 1048576, + "configuration" : { + "level" : "2" + }, + "capabilities" : { + "internal" : "Internal", + "write-through" : "Write-trough", + "instruction" : "Instruction cache" + } + }, + { + "id" : "cache:2", + "class" : "memory", + "claimed" : true, + "handle" : "DMI:0006", + "description" : "L3 cache", + "physid" : "6", + "slot" : "CPU Internal L3", + "units" : "bytes", + "size" : 6291456, + "capacity" : 6291456, + "configuration" : { + "level" : "3" + }, + "capabilities" : { + "internal" : "Internal", + "write-back" : "Write-back", + "instruction" : "Instruction cache" + } + }, + { + "id" : "memory", + "class" : "memory", + "claimed" : true, + "handle" : "DMI:0007", + "description" : "System Memory", + "physid" : "7", + "slot" : "System board or motherboard", + "units" : "bytes", + "size" : 4294967296, + "children" : [ + { + "id" : "bank:0", + "class" : "memory", + "claimed" : true, + "handle" : "DMI:0040", + "description" : "DIMM DDR3 Synchronous 1333 MHz (0.8 ns)", + "product" : "99U5474-013.A00LF", + "vendor" : "Kingston", + "physid" : "0", + "serial" : "8E087F0E", + "slot" : "ChannelB-DIMM0", + "units" : "bytes", + "size" : 2147483648, + "width" : 64, + "clock" : 1333000000 + }, + { + "id" : "bank:1", + "class" : "memory", + "claimed" : true, + "handle" : "DMI:0042", + "description" : "DIMM DDR3 Synchronous 1333 MHz (0.8 ns)", + "product" : "9905474-023.A00LF", + "vendor" : "Kingston", + "physid" : "1", + "serial" : "7805214C", + "slot" : "ChannelA-DIMM0", + "units" : "bytes", + "size" : 2147483648, + "width" : 64, + "clock" : 1333000000 + } + ] + }, + { + "id" : "cpu", + "class" : "processor", + "claimed" : true, + "handle" : "DMI:0043", + "description" : "CPU", + "product" : "Intel(R) Core(TM) i5-3330 CPU @ 3.00GHz", + "vendor" : "Intel Corp.", + "physid" : "43", + "businfo" : "cpu@0", + "version" : "Intel(R) Core(TM) i5-3330 CPU @ 3.00GHz", + "slot" : "Intel(R) Core(TM) i5-3330 CPU @ 3.00GHz", + "units" : "Hz", + "size" : 1798710000, + "capacity" : 3200000000, + "width" : 64, + "clock" : 100000000, + "configuration" : { + "cores" : "4", + "enabledcores" : "1" + }, + "capabilities" : { + "x86-64" : "64bits extensions (x86-64)", + "fpu" : "mathematical co-processor", + "fpu_exception" : "FPU exceptions reporting", + "wp" : true, + "vme" : "virtual mode extensions", + "de" : "debugging extensions", + "pse" : "page size extensions", + "tsc" : "time stamp counter", + "msr" : "model-specific registers", + "pae" : "4GB+ memory addressing (Physical Address Extension)", + "mce" : "machine check exceptions", + "cx8" : "compare and exchange 8-byte", + "apic" : "on-chip advanced programmable interrupt controller (APIC)", + "sep" : "fast system calls", + "mtrr" : "memory type range registers", + "pge" : "page global enable", + "mca" : "machine check architecture", + "cmov" : "conditional move instruction", + "pat" : "page attribute table", + "pse36" : "36-bit page size extensions", + "clflush" : true, + "dts" : "debug trace and EMON store MSRs", + "acpi" : "thermal control (ACPI)", + "mmx" : "multimedia extensions (MMX)", + "fxsr" : "fast floating point save/restore", + "sse" : "streaming SIMD extensions (SSE)", + "sse2" : "streaming SIMD extensions (SSE2)", + "ss" : "self-snoop", + "ht" : "HyperThreading", + "tm" : "thermal interrupt and status", + "pbe" : "pending break event", + "syscall" : "fast system calls", + "nx" : "no-execute bit (NX)", + "rdtscp" : true, + "constant_tsc" : true, + "arch_perfmon" : true, + "pebs" : true, + "bts" : true, + "rep_good" : true, + "nopl" : true, + "xtopology" : true, + "nonstop_tsc" : true, + "aperfmperf" : true, + "eagerfpu" : true, + "pni" : true, + "pclmulqdq" : true, + "dtes64" : true, + "monitor" : true, + "ds_cpl" : true, + "vmx" : true, + "est" : true, + "tm2" : true, + "ssse3" : true, + "cx16" : true, + "xtpr" : true, + "pdcm" : true, + "pcid" : true, + "sse4_1" : true, + "sse4_2" : true, + "x2apic" : true, + "popcnt" : true, + "tsc_deadline_timer" : true, + "aes" : true, + "xsave" : true, + "avx" : true, + "f16c" : true, + "rdrand" : true, + "lahf_lm" : true, + "ida" : true, + "arat" : true, + "epb" : true, + "pln" : true, + "pts" : true, + "dtherm" : true, + "tpr_shadow" : true, + "vnmi" : true, + "flexpriority" : true, + "ept" : true, + "vpid" : true, + "fsgsbase" : true, + "smep" : true, + "erms" : true, + "xsaveopt" : true, + "cpufreq" : "CPU Frequency scaling" + } + }, + { + "id" : "pci", + "class" : "bridge", + "claimed" : true, + "handle" : "PCIBUS:0000:00", + "description" : "Host bridge", + "product" : "Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller", + "vendor" : "Intel Corporation", + "physid" : "100", + "businfo" : "pci@0000:00:00.0", + "version" : "09", + "width" : 32, + "clock" : 33000000, + "configuration" : { + "driver" : "ivb_uncore" + }, + "children" : [ + { + "id" : "display", + "class" : "display", + "claimed" : true, + "handle" : "PCI:0000:00:02.0", + "description" : "VGA compatible controller", + "product" : "Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller", + "vendor" : "Intel Corporation", + "physid" : "2", + "businfo" : "pci@0000:00:02.0", + "version" : "09", + "width" : 64, + "clock" : 33000000, + "configuration" : { + "driver" : "i915", + "latency" : "0" + }, + "capabilities" : { + "msi" : "Message Signalled Interrupts", + "pm" : "Power Management", + "vga_controller" : true, + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing", + "rom" : "extension ROM" + } + }, + { + "id" : "communication", + "class" : "communication", + "claimed" : true, + "handle" : "PCI:0000:00:16.0", + "description" : "Communication controller", + "product" : "6 Series/C200 Series Chipset Family MEI Controller #1", + "vendor" : "Intel Corporation", + "physid" : "16", + "businfo" : "pci@0000:00:16.0", + "version" : "04", + "width" : 64, + "clock" : 33000000, + "configuration" : { + "driver" : "mei_me", + "latency" : "0" + }, + "capabilities" : { + "pm" : "Power Management", + "msi" : "Message Signalled Interrupts", + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + } + }, + { + "id" : "usb:0", + "class" : "bus", + "claimed" : true, + "handle" : "PCI:0000:00:1a.0", + "description" : "USB controller", + "product" : "6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2", + "vendor" : "Intel Corporation", + "physid" : "1a", + "businfo" : "pci@0000:00:1a.0", + "version" : "05", + "width" : 32, + "clock" : 33000000, + "configuration" : { + "driver" : "ehci-pci", + "latency" : "0" + }, + "capabilities" : { + "pm" : "Power Management", + "debug" : "Debug port", + "ehci" : "Enhanced Host Controller Interface (USB2)", + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + }, + "children" : [ + { + "id" : "usbhost", + "class" : "bus", + "claimed" : true, + "handle" : "USB:1:1", + "product" : "EHCI Host Controller", + "vendor" : "Linux 4.4.8-300.fc23.x86_64 ehci_hcd", + "physid" : "1", + "businfo" : "usb@1", + "logicalname" : "usb1", + "version" : "4.04", + "configuration" : { + "driver" : "hub", + "slots" : "2", + "speed" : "480Mbit/s" + }, + "capabilities" : { + "usb-2.00" : "USB 2.0" + }, + "children" : [ + { + "id" : "usb", + "class" : "bus", + "claimed" : true, + "handle" : "USB:1:2", + "description" : "USB hub", + "product" : "Integrated Rate Matching Hub", + "vendor" : "Intel Corp.", + "physid" : "1", + "businfo" : "usb@1:1", + "version" : "0.00", + "configuration" : { + "driver" : "hub", + "slots" : "4", + "speed" : "480Mbit/s" + }, + "capabilities" : { + "usb-2.00" : "USB 2.0" + }, + "children" : [ + { + "id" : "usb", + "class" : "input", + "claimed" : true, + "handle" : "USB:1:3", + "description" : "Mouse", + "product" : "USB Optical Mouse", + "vendor" : "Primax Electronics, Ltd", + "physid" : "2", + "businfo" : "usb@1:1.2", + "version" : "2.00", + "configuration" : { + "driver" : "usbhid", + "maxpower" : "100mA", + "speed" : "2Mbit/s" + }, + "capabilities" : { + "usb-2.00" : "USB 2.0" + } + } + ] + } + ] + } + ] + }, + { + "id" : "multimedia", + "class" : "multimedia", + "claimed" : true, + "handle" : "PCI:0000:00:1b.0", + "description" : "Audio device", + "product" : "6 Series/C200 Series Chipset Family High Definition Audio Controller", + "vendor" : "Intel Corporation", + "physid" : "1b", + "businfo" : "pci@0000:00:1b.0", + "version" : "05", + "width" : 64, + "clock" : 33000000, + "configuration" : { + "driver" : "snd_hda_intel", + "latency" : "0" + }, + "capabilities" : { + "pm" : "Power Management", + "msi" : "Message Signalled Interrupts", + "pciexpress" : "PCI Express", + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + } + }, + { + "id" : "pci:0", + "class" : "bridge", + "claimed" : true, + "handle" : "PCIBUS:0000:01", + "description" : "PCI bridge", + "product" : "6 Series/C200 Series Chipset Family PCI Express Root Port 1", + "vendor" : "Intel Corporation", + "physid" : "1c", + "businfo" : "pci@0000:00:1c.0", + "version" : "b5", + "width" : 32, + "clock" : 33000000, + "configuration" : { + "driver" : "pcieport" + }, + "capabilities" : { + "pci" : true, + "pciexpress" : "PCI Express", + "msi" : "Message Signalled Interrupts", + "pm" : "Power Management", + "normal_decode" : true, + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + } + }, + { + "id" : "pci:1", + "class" : "bridge", + "claimed" : true, + "handle" : "PCIBUS:0000:02", + "description" : "PCI bridge", + "product" : "6 Series/C200 Series Chipset Family PCI Express Root Port 5", + "vendor" : "Intel Corporation", + "physid" : "1c.4", + "businfo" : "pci@0000:00:1c.4", + "version" : "b5", + "width" : 32, + "clock" : 33000000, + "configuration" : { + "driver" : "pcieport" + }, + "capabilities" : { + "pci" : true, + "pciexpress" : "PCI Express", + "msi" : "Message Signalled Interrupts", + "pm" : "Power Management", + "normal_decode" : true, + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + }, + "children" : [ + { + "id" : "network", + "class" : "network", + "claimed" : true, + "handle" : "PCI:0000:02:00.0", + "description" : "Ethernet interface", + "product" : "RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller", + "vendor" : "Realtek Semiconductor Co., Ltd.", + "physid" : "0", + "businfo" : "pci@0000:02:00.0", + "logicalname" : "enp2s0", + "version" : "06", + "serial" : "74:d4:35:20:aa:03", + "units" : "bit/s", + "size" : 1000000000, + "capacity" : 1000000000, + "width" : 64, + "clock" : 33000000, + "configuration" : { + "autonegotiation" : "on", + "broadcast" : "yes", + "driver" : "r8169", + "driverversion" : "2.3LK-NAPI", + "duplex" : "full", + "firmware" : "rtl8168e-3_0.0.4 03/27/12", + "ip" : "10.1.1.114", + "latency" : "0", + "link" : "yes", + "multicast" : "yes", + "port" : "MII", + "speed" : "1Gbit/s" + }, + "capabilities" : { + "pm" : "Power Management", + "msi" : "Message Signalled Interrupts", + "pciexpress" : "PCI Express", + "msix" : "MSI-X", + "vpd" : "Vital Product Data", + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing", + "ethernet" : true, + "physical" : "Physical interface", + "tp" : "twisted pair", + "mii" : "Media Independant Interface", + "10bt" : "10Mbit/s", + "10bt-fd" : "10Mbit/s (full duplex)", + "100bt" : "100Mbit/s", + "100bt-fd" : "100Mbit/s (full duplex)", + "1000bt" : "1Gbit/s", + "1000bt-fd" : "1Gbit/s (full duplex)", + "autonegotiation" : "Auto-negotiation" + } + } + ] + }, + { + "id" : "pci:2", + "class" : "bridge", + "claimed" : true, + "handle" : "PCIBUS:0000:03", + "description" : "PCI bridge", + "product" : "82801 PCI Bridge", + "vendor" : "Intel Corporation", + "physid" : "1c.5", + "businfo" : "pci@0000:00:1c.5", + "version" : "b5", + "width" : 32, + "clock" : 33000000, + "capabilities" : { + "pci" : true, + "pciexpress" : "PCI Express", + "msi" : "Message Signalled Interrupts", + "pm" : "Power Management", + "subtractive_decode" : true, + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + }, + "children" : [ + { + "id" : "pci", + "class" : "bridge", + "claimed" : true, + "handle" : "PCIBUS:0000:04", + "description" : "PCI bridge", + "product" : "82801 PCI Bridge", + "vendor" : "Intel Corporation", + "physid" : "0", + "businfo" : "pci@0000:03:00.0", + "version" : "41", + "width" : 32, + "clock" : 33000000, + "capabilities" : { + "pci" : true, + "pm" : "Power Management", + "subtractive_decode" : true, + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + } + } + ] + }, + { + "id" : "usb:1", + "class" : "bus", + "claimed" : true, + "handle" : "PCI:0000:00:1d.0", + "description" : "USB controller", + "product" : "6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1", + "vendor" : "Intel Corporation", + "physid" : "1d", + "businfo" : "pci@0000:00:1d.0", + "version" : "05", + "width" : 32, + "clock" : 33000000, + "configuration" : { + "driver" : "ehci-pci", + "latency" : "0" + }, + "capabilities" : { + "pm" : "Power Management", + "debug" : "Debug port", + "ehci" : "Enhanced Host Controller Interface (USB2)", + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + }, + "children" : [ + { + "id" : "usbhost", + "class" : "bus", + "claimed" : true, + "handle" : "USB:2:1", + "product" : "EHCI Host Controller", + "vendor" : "Linux 4.4.8-300.fc23.x86_64 ehci_hcd", + "physid" : "1", + "businfo" : "usb@2", + "logicalname" : "usb2", + "version" : "4.04", + "configuration" : { + "driver" : "hub", + "slots" : "2", + "speed" : "480Mbit/s" + }, + "capabilities" : { + "usb-2.00" : "USB 2.0" + }, + "children" : [ + { + "id" : "usb", + "class" : "bus", + "claimed" : true, + "handle" : "USB:2:2", + "description" : "USB hub", + "product" : "Integrated Rate Matching Hub", + "vendor" : "Intel Corp.", + "physid" : "1", + "businfo" : "usb@2:1", + "version" : "0.00", + "configuration" : { + "driver" : "hub", + "slots" : "6", + "speed" : "480Mbit/s" + }, + "capabilities" : { + "usb-2.00" : "USB 2.0" + } + } + ] + } + ] + }, + { + "id" : "isa", + "class" : "bridge", + "claimed" : true, + "handle" : "PCI:0000:00:1f.0", + "description" : "ISA bridge", + "product" : "H61 Express Chipset Family LPC Controller", + "vendor" : "Intel Corporation", + "physid" : "1f", + "businfo" : "pci@0000:00:1f.0", + "version" : "05", + "width" : 32, + "clock" : 33000000, + "configuration" : { + "driver" : "lpc_ich", + "latency" : "0" + }, + "capabilities" : { + "isa" : true, + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + } + }, + { + "id" : "ide:0", + "class" : "storage", + "claimed" : true, + "handle" : "PCI:0000:00:1f.2", + "description" : "IDE interface", + "product" : "6 Series/C200 Series Chipset Family 4 port SATA IDE Controller", + "vendor" : "Intel Corporation", + "physid" : "1f.2", + "businfo" : "pci@0000:00:1f.2", + "version" : "05", + "width" : 32, + "clock" : 66000000, + "configuration" : { + "driver" : "ata_piix", + "latency" : "0" + }, + "capabilities" : { + "ide" : true, + "pm" : "Power Management", + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + } + }, + { + "id" : "serial", + "class" : "bus", + "handle" : "PCI:0000:00:1f.3", + "description" : "SMBus", + "product" : "6 Series/C200 Series Chipset Family SMBus Controller", + "vendor" : "Intel Corporation", + "physid" : "1f.3", + "businfo" : "pci@0000:00:1f.3", + "version" : "05", + "width" : 64, + "clock" : 33000000, + "configuration" : { + "latency" : "0" + } + }, + { + "id" : "ide:1", + "class" : "storage", + "claimed" : true, + "handle" : "PCI:0000:00:1f.5", + "description" : "IDE interface", + "product" : "6 Series/C200 Series Chipset Family 2 port SATA IDE Controller", + "vendor" : "Intel Corporation", + "physid" : "1f.5", + "businfo" : "pci@0000:00:1f.5", + "version" : "05", + "width" : 32, + "clock" : 66000000, + "configuration" : { + "driver" : "ata_piix", + "latency" : "0" + }, + "capabilities" : { + "ide" : true, + "pm" : "Power Management", + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing" + } + } + ] + }, + { + "id" : "scsi:0", + "class" : "storage", + "claimed" : true, + "physid" : "1", + "logicalname" : "scsi0", + "capabilities" : { + "emulated" : "Emulated device" + }, + "children" : [ + { + "id" : "disk", + "class" : "disk", + "claimed" : true, + "handle" : "GUID:9109bb57-aaa0-4494-bf2d-d3b88bd4aec2", + "description" : "ATA Disk", + "product" : "WDC WD2500AAKX-0", + "vendor" : "Western Digital", + "physid" : "0.0.0", + "businfo" : "scsi@0:0.0.0", + "logicalname" : "/dev/sda", + "dev" : "8:0", + "version" : "1H15", + "serial" : "WD-WCC2F1491539", + "units" : "bytes", + "size" : 250059350016, + "configuration" : { + "ansiversion" : "5", + "guid" : "9109bb57-aaa0-4494-bf2d-d3b88bd4aec2", + "logicalsectorsize" : "512", + "sectorsize" : "512" + }, + "capabilities" : { + "gpt-1.00" : "GUID Partition Table version 1.00", + "partitioned" : "Partitioned disk", + "partitioned:gpt" : "GUID partition table" + }, + "children" : [ + { + "id" : "volume:0", + "class" : "volume", + "handle" : "GUID:23280363-3a75-4421-90a3-26b4fa97010a", + "description" : "Windows FAT volume", + "vendor" : "mkfs.fat", + "physid" : "1", + "businfo" : "scsi@0:0.0.0,1", + "version" : "FAT16", + "serial" : "7f68-562e", + "size" : 208666112, + "capacity" : 209714688, + "configuration" : { + "FATs" : "2", + "filesystem" : "fat", + "name" : "EFI System Partition" + }, + "capabilities" : { + "boot" : "Contains boot code", + "fat" : "Windows FAT", + "initialized" : "initialized volume" + } + }, + { + "id" : "volume:1", + "class" : "volume", + "claimed" : true, + "handle" : "GUID:1a0fba4d-dabd-4c48-b530-31fa08309d39", + "description" : "EXT4 volume", + "vendor" : "Linux", + "physid" : "2", + "businfo" : "scsi@0:0.0.0,2", + "logicalname" : ["/dev/sda2", "/boot"], + "dev" : "8:2", + "version" : "1.0", + "serial" : "c3684c7d-36c3-4748-9552-e6c027d4410b", + "size" : 524288000, + "configuration" : { + "created" : "2016-02-01 14:04:46", + "filesystem" : "ext4", + "lastmountpoint" : "/boot", + "modified" : "2016-05-19 09:23:25", + "mount.fstype" : "ext4", + "mount.options" : "rw,seclabel,relatime,data=ordered", + "mounted" : "2016-05-19 09:23:25", + "state" : "mounted" + }, + "capabilities" : { + "journaled" : true, + "extended_attributes" : "Extended Attributes", + "large_files" : "4GB+ files", + "huge_files" : "16TB+ files", + "dir_nlink" : "directories with 65000+ subdirs", + "recover" : "needs recovery", + "extents" : "extent-based allocation", + "ext4" : true, + "ext2" : "EXT2/EXT3", + "initialized" : "initialized volume" + } + }, + { + "id" : "volume:2", + "class" : "volume", + "claimed" : true, + "handle" : "GUID:818c3c4b-1f90-4d91-82ae-1d2e04915a8d", + "description" : "LVM Physical Volume", + "vendor" : "Linux", + "physid" : "3", + "businfo" : "scsi@0:0.0.0,3", + "logicalname" : "/dev/sda3", + "dev" : "8:3", + "serial" : "CBSac6-tnC6-EY32-1oHF-bsQP-T00v-57VYIR", + "size" : 249324109824, + "capabilities" : { + "multi" : "Multi-volumes", + "lvm2" : true + } + } + ] + } + ] + }, + { + "id" : "scsi:1", + "class" : "storage", + "claimed" : true, + "physid" : "2", + "logicalname" : "scsi1", + "capabilities" : { + "emulated" : "Emulated device" + }, + "children" : [ + { + "id" : "cdrom", + "class" : "disk", + "claimed" : true, + "handle" : "SCSI:01:00:00:00", + "description" : "DVD-RAM writer", + "product" : "DVDRAM GH24NSB0", + "vendor" : "HL-DT-ST", + "physid" : "0.0.0", + "businfo" : "scsi@1:0.0.0", + "logicalname" : ["/dev/cdrom", "/dev/sr0"], + "dev" : "11:0", + "version" : "LN00", + "configuration" : { + "ansiversion" : "5", + "status" : "nodisc" + }, + "capabilities" : { + "removable" : "support is removable", + "audio" : "Audio CD playback", + "cd-r" : "CD-R burning", + "cd-rw" : "CD-RW burning", + "dvd" : "DVD playback", + "dvd-r" : "DVD-R burning", + "dvd-ram" : "DVD-RAM burning" + } + } + ] + } + ] + }, + { + "id" : "power", + "class" : "power", + "description" : "To Be Filled By O.E.M.", + "product" : "To Be Filled By O.E.M.", + "vendor" : "To Be Filled By O.E.M.", + "physid" : "1", + "version" : "To Be Filled By O.E.M.", + "serial" : "To Be Filled By O.E.M.", + "units" : "mWh", + "capacity" : 32768 + }, + { + "id" : "network:0", + "class" : "network", + "disabled" : true, + "claimed" : true, + "description" : "Ethernet interface", + "physid" : "2", + "logicalname" : "virbr0-nic", + "serial" : "52:54:00:d3:25:49", + "units" : "bit/s", + "size" : 10000000, + "configuration" : { + "autonegotiation" : "off", + "broadcast" : "yes", + "driver" : "tun", + "driverversion" : "1.6", + "duplex" : "full", + "link" : "no", + "multicast" : "yes", + "port" : "twisted pair", + "speed" : "10Mbit/s" + }, + "capabilities" : { + "ethernet" : true, + "physical" : "Physical interface" + } + }, + { + "id" : "network:1", + "class" : "network", + "claimed" : true, + "description" : "Ethernet interface", + "physid" : "3", + "logicalname" : "docker0", + "serial" : "02:42:db:25:de:ba", + "configuration" : { + "broadcast" : "yes", + "driver" : "bridge", + "driverversion" : "2.3", + "firmware" : "N/A", + "ip" : "172.17.0.1", + "link" : "no", + "multicast" : "yes" + }, + "capabilities" : { + "ethernet" : true, + "physical" : "Physical interface" + } + }, + { + "id" : "network:2", + "class" : "network", + "claimed" : true, + "description" : "Ethernet interface", + "physid" : "4", + "logicalname" : "virbr0", + "serial" : "52:54:00:d3:25:49", + "configuration" : { + "broadcast" : "yes", + "driver" : "bridge", + "driverversion" : "2.3", + "firmware" : "N/A", + "ip" : "192.168.124.1", + "link" : "no", + "multicast" : "yes" + }, + "capabilities" : { + "ethernet" : true, + "physical" : "Physical interface" + } + } + ] +} diff --git a/tests/data/person.json b/tests/data/person.json new file mode 100644 index 0000000..d93d381 --- /dev/null +++ b/tests/data/person.json @@ -0,0 +1,24 @@ +{ + "firstName": "John", + "lastName": "Smith", + "age": 25, + "address": { + "streetAddress": "21 2nd Street", + "city": "New York", + "state": "NY", + "postalCode": 10021 + }, + "phoneNumber": [ + { + "type": "home", + "number": "212 555-1234" + }, + { + "type": "fax", + "number": "646 555-4567" + } + ], + "gender": { + "type": "male" + } +} diff --git a/tests/data/person.yaml b/tests/data/person.yaml new file mode 100644 index 0000000..631927b --- /dev/null +++ b/tests/data/person.yaml @@ -0,0 +1,16 @@ +--- +firstName: John +lastName: Smith +age: 25 +address: + streetAddress: 21 2nd Street + city: New York + state: NY + postalCode: 10021 +phoneNumber: +- type: home + number: 212 555-1234 +- type: fax + number: 646 555-4567 +gender: + type: male diff --git a/tests/data/store.json b/tests/data/store.json new file mode 100644 index 0000000..3e4d5d1 --- /dev/null +++ b/tests/data/store.json @@ -0,0 +1,31 @@ +{ "store": { + "book": [ + { "category": "reference", + "author": "Nigel Rees", + "title": "Sayings of the Century", + "price": 8.95 + }, + { "category": "fiction", + "author": "Evelyn Waugh", + "title": "Sword of Honour", + "price": 12.99 + }, + { "category": "fiction", + "author": "Herman Melville", + "title": "Moby Dick", + "isbn": "0-553-21311-3", + "price": 8.99 + }, + { "category": "fiction", + "author": "J. R. R. Tolkien", + "title": "The Lord of the Rings", + "isbn": "0-395-19395-8", + "price": 22.99 + } + ], + "bicycle": { + "color": "red", + "price": 19.95 + } + } +} diff --git a/tests/data/store.yaml b/tests/data/store.yaml new file mode 100644 index 0000000..75ca7d6 --- /dev/null +++ b/tests/data/store.yaml @@ -0,0 +1,23 @@ +store: + bicycle: + color: red + price: 19.95 + book: + - author: Nigel Rees + category: reference + price: 8.95 + title: Sayings of the Century + - author: Evelyn Waugh + category: fiction + price: 12.99 + title: Sword of Honour + - author: Herman Melville + category: fiction + isbn: 0-553-21311-3 + price: 8.99 + title: Moby Dick + - author: J. R. R. Tolkien + category: fiction + isbn: 0-395-19395-8 + price: 22.99 + title: The Lord of the Rings diff --git a/tests/yaml-01.sh b/tests/yaml-01.sh new file mode 100644 index 0000000..e4170bc --- /dev/null +++ b/tests/yaml-01.sh @@ -0,0 +1,20 @@ +# data/hardware.json == (j2y data/hardware.json | y2j) + +set -o errexit -o pipefail -o nounset + +cd $(dirname $0) + +# Conversions +Y2J=../bin/yaml2json +J2Y=../bin/json2yaml + +# Slurp two files into variable +jq --null-input --raw-output \ + --slurpfile j1 data/hardware.json \ + --slurpfile j2 <(${J2Y} data/hardware.json | ${Y2J}) \ + '$j1 == $j2' | grep -q true + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh + diff --git a/tests/yaml-02.sh b/tests/yaml-02.sh new file mode 100644 index 0000000..edcbb39 --- /dev/null +++ b/tests/yaml-02.sh @@ -0,0 +1,20 @@ +# data/hardware.json == (j2y data/hardware.json | y2j) + +set -o errexit -o pipefail -o nounset + +cd $(dirname $0) + +# Conversions +Y2J=../bin/yaml2json +J2Y=../bin/json2yaml + +# Slurp two files +jq --slurp --raw-output \ + '.[0] == .[1]' \ + data/hardware.json \ + <(${J2Y} data/hardware.json | ${Y2J}) \ +| grep -q true + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh diff --git a/tests/yaml-03.sh b/tests/yaml-03.sh new file mode 100644 index 0000000..8499917 --- /dev/null +++ b/tests/yaml-03.sh @@ -0,0 +1,17 @@ +# jq q JSON == yq q YAML + +set -o errexit -o pipefail -o nounset + +cd $(dirname $0) + +# Conversions +J2Y=../bin/json2yaml +YQ=../bin/yq + +# Same result +diff <(jq --sort-keys '.store.book[1]' data/store.json | ${J2Y}) \ + <(${YQ} --sort-keys '.store.book[1]' data/store.yaml) + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh diff --git a/tests/yaml-04.sh b/tests/yaml-04.sh new file mode 100644 index 0000000..bcc1b5d --- /dev/null +++ b/tests/yaml-04.sh @@ -0,0 +1,15 @@ +# yq q YAML == s + +set -o errexit -o pipefail -o nounset + +cd $(dirname $0) + +# Query +YQ=../bin/yq + +# Extract string +[[ $(${YQ} -J -r '.store.bicycle.color' data/store.yaml) == 'red' ]] + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh diff --git a/tests/yaml-05.sh b/tests/yaml-05.sh new file mode 100644 index 0000000..b75b1d7 --- /dev/null +++ b/tests/yaml-05.sh @@ -0,0 +1,19 @@ +# data/person.json == (y2j data/person.yaml) + +set -o errexit -o pipefail -o nounset + +cd $(dirname $0) + +# Conversions +Y2J=../bin/yaml2json + +# Slurp two files +jq --sort-keys --slurp --raw-output \ + '.[0] == .[1]' \ + data/person.json \ + <(${Y2J} data/person.yaml) \ +| grep -q true + +exit + +# vim:ai:sw=4:ts=4:et:syntax=sh