Valid bench.out against a JSON schema
Commit Message
On Tue, May 27, 2014 at 09:30:00AM +0100, Will Newton wrote:
> I think last time I looked at this patch jsonschema was not a module
> Python installed by default so I suggested importing inside a
> try/catch.
Here's the updated version of the patch. I don't exit with a non-zero
error if jsonschema is not found because I didn't think it made sense
to make the 'bench' target fail because jsonschema module was not
present.
Siddhesh
* benchtests/scripts/validate_benchout.py: New script.
* benchtests/Makefile (bench-func): Call it.
* benchtests/scripts/benchout.schema.json: New file.
Comments
On 10 June 2014 08:11, Siddhesh Poyarekar <siddhesh@redhat.com> wrote:
> On Tue, May 27, 2014 at 09:30:00AM +0100, Will Newton wrote:
>> I think last time I looked at this patch jsonschema was not a module
>> Python installed by default so I suggested importing inside a
>> try/catch.
>
> Here's the updated version of the patch. I don't exit with a non-zero
> error if jsonschema is not found because I didn't think it made sense
> to make the 'bench' target fail because jsonschema module was not
> present.
>
> Siddhesh
>
> * benchtests/scripts/validate_benchout.py: New script.
> * benchtests/Makefile (bench-func): Call it.
> * benchtests/scripts/benchout.schema.json: New file.
Looks ok to me.
> diff --git a/benchtests/Makefile b/benchtests/Makefile
> index c7b70c4..fd3036d 100644
> --- a/benchtests/Makefile
> +++ b/benchtests/Makefile
> @@ -131,6 +131,8 @@ bench-func: $(binaries-bench)
> mv -f $(objpfx)bench.out $(objpfx)bench.out.old; \
> fi; \
> mv -f $(objpfx)bench.out-tmp $(objpfx)bench.out
> + scripts/validate_benchout.py $(objpfx)bench.out \
> + scripts/benchout.schema.json
>
> $(timing-type) $(binaries-bench) $(binaries-benchset): %: %.o $(objpfx)json-lib.o \
> $(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
> diff --git a/benchtests/scripts/benchout.schema.json b/benchtests/scripts/benchout.schema.json
> new file mode 100644
> index 0000000..affb7c1
> --- /dev/null
> +++ b/benchtests/scripts/benchout.schema.json
> @@ -0,0 +1,42 @@
> +{
> + "title": "benchmark",
> + "type": "object",
> + "properties": {
> + "timing_type": {
> + "type": "string"
> + },
> + "functions": {
> + "title": "Associative array of functions",
> + "type": "object",
> + "patternProperties": {
> + "^[_a-zA-Z][_a-zA-Z0-9]+$": {
> + "title": "Function names",
> + "type": "object",
> + "patternProperties": {
> + "^[_a-zA-Z0-9]*$": {
> + "title": "Function variants",
> + "type": "object",
> + "properties": {
> + "duration": {"type": "number"},
> + "iterations": {"type": "number"},
> + "max": {"type": "number"},
> + "min": {"type": "number"},
> + "mean": {"type": "number"},
> + "timings": {
> + "type": "array",
> + "items": {"type": "number"}
> + }
> + },
> + "required": ["duration", "iterations", "max", "min", "mean"],
> + "additionalProperties": false
> + }
> + },
> + "additionalProperties": false
> + }
> + },
> + "minProperties": 1
> + }
> + },
> + "required": ["timing_type", "functions"],
> + "additionalProperties": false
> +}
> diff --git a/benchtests/scripts/validate_benchout.py b/benchtests/scripts/validate_benchout.py
> new file mode 100755
> index 0000000..61a8cbd
> --- /dev/null
> +++ b/benchtests/scripts/validate_benchout.py
> @@ -0,0 +1,85 @@
> +#!/usr/bin/python
> +# Copyright (C) 2014 Free Software Foundation, Inc.
> +# This file is part of the GNU C Library.
> +#
> +# The GNU C Library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2.1 of the License, or (at your option) any later version.
> +#
> +# The GNU C Library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with the GNU C Library; if not, see
> +# <http://www.gnu.org/licenses/>.
> +"""Benchmark output validator
> +
> +Given a benchmark output file in json format and a benchmark schema file,
> +validate the output against the schema.
> +"""
> +
> +from __future__ import print_function
> +import json
> +import sys
> +import os
> +
> +try:
> + import jsonschema
> +except ImportError:
> + print('Could not find jsonschema module. Output not validated.')
> + # Return success because we don't want the bench target to fail just
> + # because the jsonschema module was not found.
> + sys.exit(os.EX_OK)
> +
> +
> +def validate_bench(benchfile, schemafile):
> + """Validate benchmark file
> +
> + Validate a benchmark output file against a JSON schema.
> +
> + Args:
> + benchfile: The file name of the bench.out file.
> + schemafile: The file name of the JSON schema file to validate
> + bench.out against.
> +
> + Exceptions:
> + jsonschema.ValidationError: When bench.out is not valid
> + jsonschema.SchemaError: When the JSON schema is not valid
> + IOError: If any of the files are not found.
> + """
> + with open(benchfile, 'r') as bfile:
> + with open(schemafile, 'r') as sfile:
> + bench = json.load(bfile)
> + schema = json.load(sfile)
> + jsonschema.validate(bench, schema)
> +
> + # If we reach here, we're all good.
> + print("Benchmark output in %s is valid." % benchfile)
> +
> +
> +def main(args):
> + """Main entry point
> +
> + Args:
> + args: The command line arguments to the program
> +
> + Returns:
> + 0 on success or a non-zero failure code
> +
> + Exceptions:
> + Exceptions thrown by validate_bench
> + """
> + if len(args) != 2:
> + print("Usage: %s <bench.out file> <bench.out schema>" % sys.argv[0],
> + file=sys.stderr)
> + return os.EX_USAGE
> +
> + validate_bench(args[0], args[1])
> + return os.EX_OK
> +
> +
> +if __name__ == '__main__':
> + sys.exit(main(sys.argv[1:]))
@@ -131,6 +131,8 @@ bench-func: $(binaries-bench)
mv -f $(objpfx)bench.out $(objpfx)bench.out.old; \
fi; \
mv -f $(objpfx)bench.out-tmp $(objpfx)bench.out
+ scripts/validate_benchout.py $(objpfx)bench.out \
+ scripts/benchout.schema.json
$(timing-type) $(binaries-bench) $(binaries-benchset): %: %.o $(objpfx)json-lib.o \
$(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
new file mode 100644
@@ -0,0 +1,42 @@
+{
+ "title": "benchmark",
+ "type": "object",
+ "properties": {
+ "timing_type": {
+ "type": "string"
+ },
+ "functions": {
+ "title": "Associative array of functions",
+ "type": "object",
+ "patternProperties": {
+ "^[_a-zA-Z][_a-zA-Z0-9]+$": {
+ "title": "Function names",
+ "type": "object",
+ "patternProperties": {
+ "^[_a-zA-Z0-9]*$": {
+ "title": "Function variants",
+ "type": "object",
+ "properties": {
+ "duration": {"type": "number"},
+ "iterations": {"type": "number"},
+ "max": {"type": "number"},
+ "min": {"type": "number"},
+ "mean": {"type": "number"},
+ "timings": {
+ "type": "array",
+ "items": {"type": "number"}
+ }
+ },
+ "required": ["duration", "iterations", "max", "min", "mean"],
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "minProperties": 1
+ }
+ },
+ "required": ["timing_type", "functions"],
+ "additionalProperties": false
+}
new file mode 100755
@@ -0,0 +1,85 @@
+#!/usr/bin/python
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+"""Benchmark output validator
+
+Given a benchmark output file in json format and a benchmark schema file,
+validate the output against the schema.
+"""
+
+from __future__ import print_function
+import json
+import sys
+import os
+
+try:
+ import jsonschema
+except ImportError:
+ print('Could not find jsonschema module. Output not validated.')
+ # Return success because we don't want the bench target to fail just
+ # because the jsonschema module was not found.
+ sys.exit(os.EX_OK)
+
+
+def validate_bench(benchfile, schemafile):
+ """Validate benchmark file
+
+ Validate a benchmark output file against a JSON schema.
+
+ Args:
+ benchfile: The file name of the bench.out file.
+ schemafile: The file name of the JSON schema file to validate
+ bench.out against.
+
+ Exceptions:
+ jsonschema.ValidationError: When bench.out is not valid
+ jsonschema.SchemaError: When the JSON schema is not valid
+ IOError: If any of the files are not found.
+ """
+ with open(benchfile, 'r') as bfile:
+ with open(schemafile, 'r') as sfile:
+ bench = json.load(bfile)
+ schema = json.load(sfile)
+ jsonschema.validate(bench, schema)
+
+ # If we reach here, we're all good.
+ print("Benchmark output in %s is valid." % benchfile)
+
+
+def main(args):
+ """Main entry point
+
+ Args:
+ args: The command line arguments to the program
+
+ Returns:
+ 0 on success or a non-zero failure code
+
+ Exceptions:
+ Exceptions thrown by validate_bench
+ """
+ if len(args) != 2:
+ print("Usage: %s <bench.out file> <bench.out schema>" % sys.argv[0],
+ file=sys.stderr)
+ return os.EX_USAGE
+
+ validate_bench(args[0], args[1])
+ return os.EX_OK
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))