From patchwork Tue Jun 11 23:31:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Steadmon X-Patchwork-Id: 10988357 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8A9D313AD for ; Tue, 11 Jun 2019 23:31:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7A145284F1 for ; Tue, 11 Jun 2019 23:31:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6E4A628918; Tue, 11 Jun 2019 23:31:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F7BC28922 for ; Tue, 11 Jun 2019 23:31:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2408123AbfFKXbn (ORCPT ); Tue, 11 Jun 2019 19:31:43 -0400 Received: from mail-pf1-f202.google.com ([209.85.210.202]:48396 "EHLO mail-pf1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404692AbfFKXbn (ORCPT ); Tue, 11 Jun 2019 19:31:43 -0400 Received: by mail-pf1-f202.google.com with SMTP id u21so7545903pfn.15 for ; Tue, 11 Jun 2019 16:31:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=o+J3IOknk86VKO2klkj8QJqhfOdxbMbsIKsJCyqwFUE=; b=vtejCj2Vqhr9ANEoxxL7GY9hGxeNM1bVufZhMaXVqRgvaqlaF8sZN1tZnpv+rIgOn7 /S+BL0FPxGFn4Xtvd+/RdzMtt4I4p0WJixQ0nXl4wWQwsAN5Yg1lzG0DOx6ULrbjbQCb 0aEJ6kDBjWwDy4+UWe3i/H+dEU9Xlr7lein2SVAr6Qn1NiB1N5KwhVzpiYSuZiOFcYVm F9jDxyI14r0RJEj71++GEIt5/PG6k/NFTjtJDANnA5EX71pLWZcjeILQofYmgPMaRLs5 FfugNnsdrKQpjykxxJtzrQCiciXH5SVYO3vlXtrLm9yu+H8d84vE87a6Ektenn75XasX 5NPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=o+J3IOknk86VKO2klkj8QJqhfOdxbMbsIKsJCyqwFUE=; b=SWSFEJV8zMkOqItru9Kv7CMnxJN4drw6rR6YX2bLiVmYzmq0EDmcOBjP476uWkX1xW vH8dzDvBDEa7SEo4R31b6UhYBLM8rgU55kf09BlCR8moBdxc4btDHAAmNuA2b38cmM9Y TkJcjdcz70aEhZzTMLX8PGZ1D0dw9/NMdfIQTmDOtVAwXkScJILDaNz5kDaRBH7HQmIq ktQLytEyFxUaEPtw9p7BrhI12jmAWcQcuy6q7J+MicjCP/stWtLdA5VmAvACqs3UWtJK P3b8iPqqc7i43g/A8z7EQdYl74TwbovdbLzyP337aBBpoYi0Wrke7OJEkY8XAvFFuTbD JPyA== X-Gm-Message-State: APjAAAWZNdhqDZr7k3Fg1+GW1flquj6zzzOd4NEeoF+w6RnHEXHaGh1k C8i7jb4ukbuN2H5exF+yWfm8H77ywU+kjMnbTbLDDuFxmA899TSXEK+zKOZr+ZLu6gTgikehv5C Dki5YjFN0D69j+B7wkTwqE3Mqb5lqrP8fGA7Aj0K36vdqB3dD42++yHFYksYHl/I= X-Google-Smtp-Source: APXvYqwo2gZDjJ1OudIbJkXpNX1BJ+TbSfqUBZxtHpuwYmY6OLZzhczLv+pvDTotdc8uSLAKg9DIA02rXsQq+w== X-Received: by 2002:a63:2ad2:: with SMTP id q201mr21438463pgq.94.1560295902011; Tue, 11 Jun 2019 16:31:42 -0700 (PDT) Date: Tue, 11 Jun 2019 16:31:35 -0700 In-Reply-To: Message-Id: <8bcd72a762f0fd349f8bf7d0b134cc7033ae6f00.1560295286.git.steadmon@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.22.0.410.gd8fdbe21b5-goog Subject: [RFC PATCH 1/3] trace2: correct trace2 field name documentation From: Josh Steadmon To: git@vger.kernel.org, git@jeffhostetler.com Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Correct the api-trace2 documentation, which lists "signal" as an expected field for the signal event type, but which actually outputs "signo" as the field name. Signed-off-by: Josh Steadmon --- Documentation/technical/api-trace2.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/technical/api-trace2.txt b/Documentation/technical/api-trace2.txt index 23c3cc7a37..fd1e628944 100644 --- a/Documentation/technical/api-trace2.txt +++ b/Documentation/technical/api-trace2.txt @@ -668,7 +668,7 @@ completed.) "event":"signal", ... "t_abs":0.001227, # elapsed time in seconds - "signal":13 # SIGTERM, SIGINT, etc. + "signo":13 # SIGTERM, SIGINT, etc. } ------------ From patchwork Tue Jun 11 23:31:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Steadmon X-Patchwork-Id: 10988361 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2C23B14BB for ; Tue, 11 Jun 2019 23:31:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19C6828923 for ; Tue, 11 Jun 2019 23:31:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0DEEF2892C; Tue, 11 Jun 2019 23:31:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EE17D28923 for ; Tue, 11 Jun 2019 23:31:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2408133AbfFKXbr (ORCPT ); Tue, 11 Jun 2019 19:31:47 -0400 Received: from mail-vs1-f74.google.com ([209.85.217.74]:49752 "EHLO mail-vs1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404692AbfFKXbq (ORCPT ); Tue, 11 Jun 2019 19:31:46 -0400 Received: by mail-vs1-f74.google.com with SMTP id 184so4818192vsw.16 for ; Tue, 11 Jun 2019 16:31:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=MjryO5Ekus0jjjA7KOGE9LdJrehRl2VsZmp7t0u4+u4=; b=Vff2WnD2V1BvPdWlVP6IHMz9MYyq0fCpemOq4oVZZhwKZXexo3UUp5M1+ZySmWrsEE 2SXqBLSEzdPtfZnwYFM5X4umgjch+WqdUfbXWikgnydMFy5/DzeN/d+AEO4GytH0lpfa gXTsHHgUWCdjNVjvnLTqX3JJhz2mM3udvwL/ONeS6379l/dpssCsUYxGTtV86jT/xkgS sU3FVVek/J9iKUAUyA2A6mKEConT2Inkv4JfbmCuoKwVon/rLngrkPzHe8fh6WDU2Kp9 2FUPd/m6ld6zEanqz5oFVK/qIAvXnBKibvnBBYvDGKt3swSJjphVjs6mzTbx46LGs5/A Tecg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=MjryO5Ekus0jjjA7KOGE9LdJrehRl2VsZmp7t0u4+u4=; b=GmjQhT1kZthpwwHAlwSKEwaJlZ7JAhk+Emjjb8ia9lmyyNWs0Ev52VdgVJPOG7Dnnz QOCZXRZTba1KWZPlE64ThbFhQwQsgdCM4CNtPAshJL4gsMsiLMXNVL//1XnNYV2w3s/+ W1VObzqBSZ+aSy1vQ1n4DzxSqmTUZpNXb47i2BC922rjZW9QPPTdqHR0Frm9N+sSgJnF 1gtBYqwMdTMeQC6oZREZfE7BdPWHSXmsKoqSpbP9iLubdTSDYjHmdiyJkgLTeuDIWYDl C+AsRJySBfPapAXzKjw6B0RIej4MSWeOBUjhUz/NOuFjmILTISLG/XET1gdG4hut3GLy C3PQ== X-Gm-Message-State: APjAAAX1BKogJPWvn0v9QKC3aze3JAhJ2l9PKVeMZwW0jebhGKkV1SQs cVYdnDAHNeN5CL3XfV6nSAt6/YdERrRh9uY7NouCx+Q2p2AETC8rZ8El2XRzNguSRnBYB8v+TEz PRY0/7CBVIO8k6p/4ejFCxTYzAFsWWCWpNxQeu4FhieQcs4Djc+V77kZaWdF/FYg= X-Google-Smtp-Source: APXvYqwe1M+HmdSRN/bogjU4aD4WuIYibtOpZ3dQl1KzkY3nh5XNCg+UYbQdNcAQGLjLUYIX04DGFSG7LK5OXg== X-Received: by 2002:ab0:1004:: with SMTP id f4mr14998095uab.79.1560295904930; Tue, 11 Jun 2019 16:31:44 -0700 (PDT) Date: Tue, 11 Jun 2019 16:31:36 -0700 In-Reply-To: Message-Id: <8dd0277222efa265f1e911c8476305feb3c2c3fb.1560295286.git.steadmon@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.22.0.410.gd8fdbe21b5-goog Subject: [RFC PATCH 2/3] trace2: Add a JSON schema for trace2 events From: Josh Steadmon To: git@vger.kernel.org, git@jeffhostetler.com Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Define a JSON schema[1] that can be used to validate trace2 event objects. This can be used to add regression tests to verify that the event output format does not change unexpectedly. Two versions of the schema are provided: * event_schema.json is more permissive. It verifies that all expected fields are present in each trace event, but it allows traces to have unexpected additional fields. This allows the schema to be specified more concisely by factoring out the common fields into a reusable sub-schema. * strict_schema.json is more restrictive. It verifies that all expected fields are present and no unexpected fields are present in each trace event. Due to this additional restriction, the common fields cannot be factored out into a re-usable subschema (at least as-of draft-07) [2], and must be repeated for each event definition. [1]: https://json-schema.org/ [2]: https://json-schema.org/understanding-json-schema/reference/combining.html#allof Signed-off-by: Josh Steadmon --- t/trace_schema_validator/event_schema.json | 398 +++++++++++++++ t/trace_schema_validator/strict_schema.json | 511 ++++++++++++++++++++ 2 files changed, 909 insertions(+) create mode 100644 t/trace_schema_validator/event_schema.json create mode 100644 t/trace_schema_validator/strict_schema.json diff --git a/t/trace_schema_validator/event_schema.json b/t/trace_schema_validator/event_schema.json new file mode 100644 index 0000000000..5f6cfb11e7 --- /dev/null +++ b/t/trace_schema_validator/event_schema.json @@ -0,0 +1,398 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://git-scm.com/schemas/event_schema.json", + "title": "trace2 permissive schema", + "description": "Permissive schema for trace2 event output that does not fail in the presence of unexpected fields.", + + "definitions": { + "event_common_fields": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" } + }, + "required": [ "sid", "thread" ] + }, + + "version_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "version" }, + "evt": { "const": "1" }, + "exe": { "type": "string" } + }, + "required": [ "event", "evt", "exe" ] + } + ] + }, + + "start_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "start" }, + "t_abs": { "type": "number" }, + "argv": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": [ "event", "t_abs", "argv" ] + } + ] + }, + + "exit_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "exit" }, + "t_abs": { "type": "number" }, + "code": { "type": "integer" } + }, + "required": [ "event", "t_abs", "code" ] + } + ] + }, + + "atexit_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "atexit" }, + "t_abs": { "type": "number" }, + "code": { "type": "integer" } + }, + "required": [ "event", "t_abs", "code" ] + } + ] + }, + + "signal_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "signal" }, + "t_abs": { "type": "number" }, + "signo": { "type": "integer" } + }, + "required": [ "event", "t_abs", "signo" ] + } + ] + }, + + "error_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "error" }, + "msg": { "type": "string" }, + "fmt": { "type": "string" } + }, + "required": [ "event", "msg", "fmt" ] + } + ] + }, + + "cmd_path_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "cmd_path" }, + "path": { "type": "string" } + }, + "required": [ "event", "path" ] + } + ] + }, + + "cmd_name_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "cmd_name" }, + "name": { "type": "string" }, + "hierarchy": { "type": "string" } + }, + "required": [ "event", "name", "hierarchy" ] + } + ] + }, + + "cmd_mode_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "cmd_mode" }, + "name": { "type": "string" } + }, + "required": [ "event", "name" ] + } + ] + }, + + "alias_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "alias" }, + "alias": { "type": "string" }, + "argv": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": [ "event", "alias", "argv" ] + } + ] + }, + + "child_start_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "child_start" }, + "child_id": { "type": "integer" }, + "child_class": { "type": "string" }, + "use_shell": { "type": "boolean" }, + "argv": { + "type": "array", + "items": { "type": "string" } + }, + "hook_name": { "type": "string" }, + "cd": { "type": "string" } + }, + "required": [ + "event", "child_id", "child_class", "use_shell", "argv" + ] + } + ] + }, + + "child_exit_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "child_exit" }, + "child_id": { "type": "integer" }, + "pid": { "type": "integer" }, + "code": { "type": "integer" }, + "t_rel": { "type": "number" } + }, + "required": [ "event", "child_id", "pid", "code", "t_rel" ] + } + ] + }, + + "exec_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "exec" }, + "exec_id": { "type": "integer" }, + "exe": { "type": "string" }, + "argv": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": [ "event", "exec_id", "exe", "argv" ] + } + ] + }, + + "exec_result_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "exec_result" }, + "exec_id": { "type": "integer" }, + "code": { "type": "integer" } + }, + "required": [ "event", "exec_id", "code" ] + } + ] + }, + + "thread_start_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "thread_start" }, + "thread": { "type": "string" } + }, + "required": [ "event", "thread" ] + } + ] + }, + + "thread_exit_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "thread_exit" }, + "thread": { "type": "string" }, + "t_rel": { "type": "number" } + }, + "required": [ "event", "thread", "t_rel" ] + } + ] + }, + + "def_param_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "def_param" }, + "param": { "type": "string" }, + "value": { "type": "string" } + }, + "required": [ "event", "param", "value" ] + } + ] + }, + + "def_repo_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "def_repo" }, + "repo": { "type": "integer" }, + "worktree": { "type": "string" } + }, + "required": [ "event", "repo", "worktree" ] + } + ] + }, + + "region_enter_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "region_enter" }, + "repo": { "type": "integer" }, + "nesting": { "type": "integer" }, + "category": { "type": "string" }, + "label": { "type": "string" }, + "msg": { "type": "string" } + }, + "required": [ "event", "nesting" ] + } + ] + }, + + "region_leave_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "region_leave" }, + "repo": { "type": "integer" }, + "t_rel": { "type": "number" }, + "nesting": { "type": "integer" }, + "category": { "type": "string" }, + "label": { "type": "string" }, + "msg": { "type": "string" } + }, + "required": [ "event", "t_rel", "nesting" ] + } + ] + }, + + "data_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "data" }, + "repo": { "type": "integer" }, + "t_abs": { "type": "number" }, + "t_rel": { "type": "number" }, + "nesting": { "type": "integer" }, + "category": { "type": "string" }, + "key": { "type": "string" }, + "value": { "type": "string" } + }, + "required": [ + "event", "t_abs", "t_rel", "nesting", "category", "key", + "value" + ] + } + ] + }, + + "data-json_event": { + "allOf": [ + { "$ref": "#/definitions/event_common_fields" }, + { + "properties": { + "event": { "const": "data-json" }, + "repo": { "type": "integer" }, + "t_abs": { "type": "number" }, + "t_rel": { "type": "number" }, + "nesting": { "type": "integer" }, + "category": { "type": "string" }, + "key": { "type": "string" }, + "value": true + }, + "required": [ + "event", "t_abs", "t_rel", "nesting", "category", "key", + "value" + ] + } + ] + } + }, + + "oneOf": [ + { "$ref": "#/definitions/version_event" }, + { "$ref": "#/definitions/start_event" }, + { "$ref": "#/definitions/exit_event" }, + { "$ref": "#/definitions/atexit_event" }, + { "$ref": "#/definitions/signal_event" }, + { "$ref": "#/definitions/error_event" }, + { "$ref": "#/definitions/cmd_path_event" }, + { "$ref": "#/definitions/cmd_name_event" }, + { "$ref": "#/definitions/cmd_mode_event" }, + { "$ref": "#/definitions/alias_event" }, + { "$ref": "#/definitions/child_start_event" }, + { "$ref": "#/definitions/child_exit_event" }, + { "$ref": "#/definitions/exec_event" }, + { "$ref": "#/definitions/exec_result_event" }, + { "$ref": "#/definitions/thread_start_event" }, + { "$ref": "#/definitions/thread_exit_event" }, + { "$ref": "#/definitions/def_param_event" }, + { "$ref": "#/definitions/def_repo_event" }, + { "$ref": "#/definitions/region_enter_event" }, + { "$ref": "#/definitions/region_leave_event" }, + { "$ref": "#/definitions/data_event" }, + { "$ref": "#/definitions/data-json_event" } + ] +} diff --git a/t/trace_schema_validator/strict_schema.json b/t/trace_schema_validator/strict_schema.json new file mode 100644 index 0000000000..239d852ee9 --- /dev/null +++ b/t/trace_schema_validator/strict_schema.json @@ -0,0 +1,511 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://git-scm.com/schemas/event_schema.json", + "title": "trace2 strict schema", + "description": "Strict schema for trace2 event output that verifies there are no unexpected fields.", + + "definitions": { + "version_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "version" }, + "evt": { "const": "1" }, + "exe": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "evt", "exe" ], + "additionalProperties": false + }, + + "start_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "start" }, + "t_abs": { "type": "number" }, + "argv": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": [ "sid", "thread", "time", "event", "t_abs", "argv" ], + "additionalProperties": false + }, + + "exit_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "exit" }, + "t_abs": { "type": "number" }, + "code": { "type": "integer" } + }, + "required": [ "sid", "thread", "event", "t_abs", "code" ], + "additionalProperties": false + }, + + "atexit_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "atexit" }, + "t_abs": { "type": "number" }, + "code": { "type": "integer" } + }, + "required": [ "sid", "thread", "time", "event", "t_abs", "code" ], + "additionalProperties": false + }, + + "signal_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "signal" }, + "t_abs": { "type": "number" }, + "signo": { "type": "integer" } + }, + "required": [ "sid", "thread", "event", "t_abs", "signo" ], + "additionalProperties": false + }, + + "error_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "error" }, + "msg": { "type": "string" }, + "fmt": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "msg", "fmt" ], + "additionalProperties": false + }, + + "cmd_path_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "cmd_path" }, + "path": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "path" ], + "additionalProperties": false + }, + + "cmd_name_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "cmd_name" }, + "name": { "type": "string" }, + "hierarchy": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "name", "hierarchy" + ], + "additionalProperties": false + }, + + "cmd_mode_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "cmd_mode" }, + "name": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "name" ], + "additionalProperties": false + }, + + "alias_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "alias" }, + "alias": { "type": "string" }, + "argv": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": [ "sid", "thread", "event", "alias", "argv" ], + "additionalProperties": false + }, + + "child_start_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "child_start" }, + "child_id": { "type": "integer" }, + "child_class": { "type": "string" }, + "use_shell": { "type": "boolean" }, + "argv": { + "type": "array", + "items": { "type": "string" } + }, + "hook_name": { "type": "string" }, + "cd": { "type": "string" } + }, + "required": [ + "sid", "thread", "event", "child_id", "child_class", + "use_shell", "argv" + ], + "additionalProperties": false + }, + + "child_exit_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "child_exit" }, + "child_id": { "type": "integer" }, + "pid": { "type": "integer" }, + "code": { "type": "integer" }, + "t_rel": { "type": "number" } + }, + "required": [ + "sid", "thread", "event", "child_id", "pid", "code", "t_rel" + ], + "additionalProperties": false + }, + + "exec_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "exec" }, + "exec_id": { "type": "integer" }, + "exe": { "type": "string" }, + "argv": { + "type": "array", + "items": { "type": "string" } + } + }, + "required": [ "sid", "thread", "event", "exec_id", "exe", "argv" ], + "additionalProperties": false + }, + + "exec_result_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "exec_result" }, + "exec_id": { "type": "integer" }, + "code": { "type": "integer" } + }, + "required": [ "sid", "thread", "event", "exec_id", "code" ], + "additionalProperties": false + }, + + "thread_start_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "thread_start" } + }, + "required": [ "sid", "thread", "event" ], + "additionalProperties": false + }, + + "thread_exit_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "thread_exit" }, + "t_rel": { "type": "number" } + }, + "required": [ "sid", "thread", "event", "t_rel" ], + "additionalProperties": false + }, + + "def_param_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "def_param" }, + "param": { "type": "string" }, + "value": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "param", "value" ], + "additionalProperties": false + }, + + "def_repo_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "def_repo" }, + "worktree": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "repo", "worktree" ], + "additionalProperties": false + }, + + "region_enter_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "region_enter" }, + "nesting": { "type": "integer" }, + "category": { "type": "string" }, + "label": { "type": "string" }, + "msg": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "nesting" ], + "additionalProperties": false + }, + + "region_leave_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "region_leave" }, + "t_rel": { "type": "number" }, + "nesting": { "type": "integer" }, + "category": { "type": "string" }, + "label": { "type": "string" }, + "msg": { "type": "string" } + }, + "required": [ "sid", "thread", "event", "t_rel", "nesting" ], + "additionalProperties": false + }, + + "data_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "data" }, + "t_abs": { "type": "number" }, + "t_rel": { "type": "number" }, + "nesting": { "type": "integer" }, + "category": { "type": "string" }, + "key": { "type": "string" }, + "value": { "type": "string" } + }, + "required": [ + "sid", "thread", "event", "t_abs", "t_rel", "nesting", + "category","key", "value" + ], + "additionalProperties": false + }, + + "data-json_event": { + "type": "object", + "properties": { + "sid": { "type": "string" }, + "thread": { "type": "string" }, + "time": { + "type": "string", + "format": "date-time" + }, + "file": { "type": "string" }, + "line": { "type": "integer" }, + "repo": { "type": "integer" }, + "event": { "const": "data-json" }, + "t_abs": { "type": "number" }, + "t_rel": { "type": "number" }, + "nesting": { "type": "integer" }, + "category": { "type": "string" }, + "key": { "type": "string" }, + "value": true + }, + "required": [ + "sid", "thread", "event", "t_abs", "t_rel", "nesting", + "category", "key", "value" + ], + "additionalProperties": false + } + }, + + "oneOf": [ + { "$ref": "#/definitions/version_event" }, + { "$ref": "#/definitions/start_event" }, + { "$ref": "#/definitions/exit_event" }, + { "$ref": "#/definitions/atexit_event" }, + { "$ref": "#/definitions/signal_event" }, + { "$ref": "#/definitions/error_event" }, + { "$ref": "#/definitions/cmd_path_event" }, + { "$ref": "#/definitions/cmd_name_event" }, + { "$ref": "#/definitions/cmd_mode_event" }, + { "$ref": "#/definitions/alias_event" }, + { "$ref": "#/definitions/child_start_event" }, + { "$ref": "#/definitions/child_exit_event" }, + { "$ref": "#/definitions/exec_event" }, + { "$ref": "#/definitions/exec_result_event" }, + { "$ref": "#/definitions/thread_start_event" }, + { "$ref": "#/definitions/thread_exit_event" }, + { "$ref": "#/definitions/def_param_event" }, + { "$ref": "#/definitions/def_repo_event" }, + { "$ref": "#/definitions/region_enter_event" }, + { "$ref": "#/definitions/region_leave_event" }, + { "$ref": "#/definitions/data_event" }, + { "$ref": "#/definitions/data-json_event" } + ] +} From patchwork Tue Jun 11 23:31:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Steadmon X-Patchwork-Id: 10988359 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E31A013AD for ; Tue, 11 Jun 2019 23:31:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D05F628922 for ; Tue, 11 Jun 2019 23:31:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AEEFC28924; Tue, 11 Jun 2019 23:31:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3BF37284F1 for ; Tue, 11 Jun 2019 23:31:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2408144AbfFKXbt (ORCPT ); Tue, 11 Jun 2019 19:31:49 -0400 Received: from mail-pf1-f201.google.com ([209.85.210.201]:37413 "EHLO mail-pf1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2408126AbfFKXbs (ORCPT ); Tue, 11 Jun 2019 19:31:48 -0400 Received: by mail-pf1-f201.google.com with SMTP id x18so10667985pfj.4 for ; Tue, 11 Jun 2019 16:31:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=SXY/CgbexSQiBdos0S0dmLpXZIbKQ2KMSCjVtNiurmA=; b=AB4bfS2rPdw/4Qb88y8eYpc9z6ScpXlSOW2KtMw0Kjn9VAKIdSs+4WhduIBjkSp/0U tZP1wD28ZtW8osKoDEyiSnS4nQvFmny/a5/nnKJJAKX3LYeljv3KHbVDhw79pTCQQp9Z asIKAiu0GJMZdddWRXLVor5HYnxxWzNctsMgi8dz6tsarP2cUBGe0kT/UTMWUpItYCQQ 6IcemzrPgI8vQIfSWWt46k3NjsleGLoS3XNhVXV7y5et/DWNJpIkGQDlfjnRE3IWqKTG tdmRpfWXdI1XGYorbshmDfXdIxxpE9k+7BNOT+JMu4liBc48FHM3B8qrZITenfUXJ4cl SYmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=SXY/CgbexSQiBdos0S0dmLpXZIbKQ2KMSCjVtNiurmA=; b=RvU/6Ddp4T4mVHH2zW6GyJKnbd6fRaylgZKbnvYMEzzHoxRmEEY4NXdZH2IUftP5v0 OvyWPZj+ukpBwmHy/5aNEZSDmcrD8m3Y1y/2eO/q53joFxIuIWrI/ylBR475Ldrj8YcU zWSY3oHFatN/4grqu4QqgNXzM6WhEn6ZuUEIySPyHeMm9K+iemoF2g0DriCZRAbBm+jm WBQ53OmRaF5FKXmTBNJiH8jMVshpf6fLAAkH5d+jhwtU+TTivsfvTExoJEw77YEvJJ59 G0rbU49rSjxsK1rnwHlXwHkjjcpNHy+zh0xUqrRqxDh/iZvkEvJUBeSiV1CRaAqP6Osg QowA== X-Gm-Message-State: APjAAAVEAQKpySXGyk3waT/XCq0aRT2lG+Iko7xFsA3ftprELPGHyd+l xJIvNg8yXIQP6E93OsPGyfcGmUHDQlGukDvF0WPo1RqmSOcshsahoWClyJf0Q6ei1DEtv2tgzjZ /cR4mBI0UrXnkckmWGpYE4kzDDviEPDY+96s+g3WMk1PR0KGzmHjrgqLwBGEaLiY= X-Google-Smtp-Source: APXvYqzLNsuvAbJ/q4xkv9L3R5hFIU5VUFE/XzPxGm8CrVjxdjQABY42zHtWXh1hOTy4uE9bQYbsXukPvYtz2Q== X-Received: by 2002:a65:4907:: with SMTP id p7mr22086792pgs.288.1560295907197; Tue, 11 Jun 2019 16:31:47 -0700 (PDT) Date: Tue, 11 Jun 2019 16:31:37 -0700 In-Reply-To: Message-Id: <7475c6220895d96cdc7d25d6edea70e2f978526b.1560295286.git.steadmon@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.22.0.410.gd8fdbe21b5-goog Subject: [RFC PATCH 3/3] trace2: add a schema validator for trace2 events From: Josh Steadmon To: git@vger.kernel.org, git@jeffhostetler.com Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP trace_schema_validator can be used to verify that trace2 event output conforms to the expectations set by the API documentation and codified in event_schema.json (or strict_schema.json). This allows us to build a regression test to verify that trace2 output does not change unexpectedly. Signed-off-by: Josh Steadmon --- t/trace_schema_validator/.gitignore | 1 + t/trace_schema_validator/Makefile | 10 +++ .../trace_schema_validator.go | 74 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 t/trace_schema_validator/.gitignore create mode 100644 t/trace_schema_validator/Makefile create mode 100644 t/trace_schema_validator/trace_schema_validator.go diff --git a/t/trace_schema_validator/.gitignore b/t/trace_schema_validator/.gitignore new file mode 100644 index 0000000000..c3f1e04e9e --- /dev/null +++ b/t/trace_schema_validator/.gitignore @@ -0,0 +1 @@ +trace_schema_validator diff --git a/t/trace_schema_validator/Makefile b/t/trace_schema_validator/Makefile new file mode 100644 index 0000000000..ed22675e5d --- /dev/null +++ b/t/trace_schema_validator/Makefile @@ -0,0 +1,10 @@ +.PHONY: fetch_deps clean + +trace_schema_validator: fetch_deps trace_schema_validator.go + go build + +fetch_deps: + go get github.com/xeipuuv/gojsonschema + +clean: + rm -f trace_schema_validator diff --git a/t/trace_schema_validator/trace_schema_validator.go b/t/trace_schema_validator/trace_schema_validator.go new file mode 100644 index 0000000000..51dc9ec608 --- /dev/null +++ b/t/trace_schema_validator/trace_schema_validator.go @@ -0,0 +1,74 @@ +// trace_schema_validator validates individual lines of an input file against a +// provided JSON-Schema for git trace2 event output. +// +// Traces can be collected by setting the GIT_TRACE2_EVENT environment variable +// to an absolute path and running any Git command; traces will be appended to +// the file. +// +// Traces can then be verified like so: +// trace_schema_validator \ +// --trace2_event_file /path/to/trace/output \ +// --schema_file /path/to/schema +package main + +import ( + "bufio" + "flag" + "log" + "os" + "path/filepath" + + "github.com/xeipuuv/gojsonschema" +) + +// Required flags +var schemaFile = flag.String("schema_file", "", "JSON-Schema filename") +var trace2EventFile = flag.String("trace2_event_file", "", "trace2 event filename") + +func main() { + flag.Parse() + if *schemaFile == "" || *trace2EventFile == "" { + log.Fatal("Both --schema_file and --trace2_event_file are required.") + } + schemaURI, err := filepath.Abs(*schemaFile) + if err != nil { + log.Fatal("Can't get absolute path for schema file: ", err) + } + schemaURI = "file://" + schemaURI + + schemaLoader := gojsonschema.NewReferenceLoader(schemaURI) + schema, err := gojsonschema.NewSchema(schemaLoader) + if err != nil { + log.Fatal("Problem loading schema: ", err) + } + + tracesFile, err := os.Open(*trace2EventFile) + if err != nil { + log.Fatal("Problem opening trace file: ", err) + } + defer tracesFile.Close() + + scanner := bufio.NewScanner(tracesFile) + + count := 0 + for ; scanner.Scan(); count++ { + event := gojsonschema.NewStringLoader(scanner.Text()) + result, err := schema.Validate(event) + if err != nil { + log.Fatal(err) + } + if !result.Valid() { + log.Print("Trace event is invalid: ", scanner.Text()) + for _, desc := range result.Errors() { + log.Print("- ", desc) + } + os.Exit(1) + } + } + + if err := scanner.Err(); err != nil { + log.Fatal("Scanning error: ", err) + } + + log.Print("Validated events: ", count) +}