.. _ogn_reference_guide:

OGN Reference Guide
===================

This is a detailed guide to the syntax of the .ogn file. All of the keywords supported are described in detail, and a
simplified JSON schema file is provided for reference.

Each of the described elements contains an example of its use in a .ogn file to illustrate the syntax.
For a more detailed guide on how each of the elements are used see the :ref:`ogn_user_guide`.

.. contents::

..

..

====================================    ====
Node Level Keywords                     Attribute Level Keywords
====================================    ====
:ref:`ogn_keyword_node_description`     :ref:`ogn_keyword_attribute_description`
:ref:`ogn_keyword_node_exclude`         :ref:`ogn_keyword_attribute_default`
:ref:`ogn_keyword_node_icon`            :ref:`ogn_keyword_attribute_deprecated`
:ref:`ogn_keyword_node_memoryType`      :ref:`ogn_keyword_attribute_memoryType`
:ref:`ogn_keyword_node_cudaPointers`    :ref:`ogn_keyword_attribute_metadata`
:ref:`ogn_keyword_node_metadata`        :ref:`maximum <ogn_keyword_attribute_range>`
:ref:`ogn_keyword_node_singleton`       :ref:`minimum <ogn_keyword_attribute_range>`
:ref:`ogn_keyword_node_tags`            :ref:`ogn_keyword_attribute_optional`
:ref:`ogn_keyword_node_tokens`          :ref:`ogn_keyword_attribute_type`
:ref:`ogn_keyword_node_uiName`          :ref:`ogn_keyword_attribute_uiName`
:ref:`ogn_keyword_node_version`         :ref:`ogn_keyword_attribute_uiType`
:ref:`ogn_keyword_node_language`        :ref:`ogn_keyword_attribute_unvalidated`
:ref:`ogn_keyword_node_scheduling`
:ref:`ogn_keyword_node_categories`
====================================    ====


------------

Basic Structure
---------------

See the :ref:`omnigraph_naming_conventions` for guidance on how to name your files, nodes, and attributes.

.. code-block:: json

    {
        "NodeName": {
            "NODE_PROPERTY": "NODE_PROPERTY_VALUE",
            "inputs": "ATTRIBUTE_DICTIONARY",
            "outputs": "ATTRIBUTE_DICTIONARY",
            "state": "ATTRIBUTE_DICTIONARY",
            "tests": "TEST_DATA"
        }
    }

The :ref:`NODE_PROPERTY<ogn_node_property_keywords>` values are keywords recognized at the node level. The values
in ``NODE_PROPERTY_VALUE`` will vary based on the specific keyword to which they pertain.

The :ref:`ATTRIBUTE_DICTIONARY<ogn_attribute_dictionaries>` sections contain all of the information required to
define the subset of attributes, each containing a set of :ref:`ogn_attribute_property_keywords` that describe the
attribute.

Lastly the :ref:`TEST_DATA<ogn_test_data>` section contains information required to construct one or more Python
tests that exercise the basic node operation.

Comments
--------
JSON files do not have a syntax for adding comments, however in order to allow for adding descriptions or
disabled values to a .ogn file the leading character "$" will treat the key in any key/value pair as a
comment. So while ``"description":"Hello"`` will be treated as a value to be added to the node definition,
``"$description":"Hello"`` will be ignored and not parsed.

Comments can appear pretty much anywhere in your file. They are used extensively in the :ref:`ogn_tutorial_nodes` to
describe the file contents.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 1-4
    :emphasize-lines: 3

.. _ogn_node_property_keywords:

Node Property Keywords
----------------------
These are the elements that can appear in the `NODE_PROPERTY` section. The values they describe pertain to the node
type as a whole.

.. _ogn_keyword_node_description:
.. rubric:: description

The *description* key value is required on all nodes and will be used in the generated documentation of the node.
You can embed reStructuredText code in the string to be rendered in the final node documentation, though it will
appear as-is in internal documentation such as Python docstrings.

The value can be a string or a list of strings. If it is a list, they will be concatenated as appropriate in the
locations they are used. (Linefeeds preserved in Python docstrings, turned into a single space for text documentation,
prepended with comment directives in code...)

.. tip::

    This mandatory string should inform users exactly what function the node performs, as concisely as possible.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 1-8
    :emphasize-lines: 4-7

.. _ogn_keyword_node_version:
.. rubric:: version

The integer value *version* defines the version number of the current node definition. It is up to the node writer
how to manage the encoding of version levels in the integer value. (For example a node might encode a major version
of 3, a minor version of 6, and a patch version of 12 in two digit groups as the integer 30612, or it might simply
use monotonic increasing values for versions 1, 2, 3...)

.. tip::

    This mandatory value can be anything but by convention should start at 1.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 4-9
    :emphasize-lines: 5

.. _ogn_keyword_node_exclude:
.. rubric:: exclude

Some node types will not be interested in all generated files, e.g. if the node is a Python node it will not need the
C++ interface. Any of the generated files can be skipped by including it in a list of strings whose key is *exclude*.
Here is a node which excludes all generated output, something you might do if you are developing the description of a
new node and just want the node syntax to validate without generating code.

Legal values to include in the exclusion list are **"c++"**, **"docs"**, **"icon"**, **"python"**, **"template"**,
**"tests"**, or **"usd"**, in any combination.

.. note::

    C++ is automatically excluded when the implementation language is Python, however when the implementation language
    is C++ there will still be a Python interface class generated for convenience. It will have less functionality
    than for nodes implemented in Python and is mainly intended to provide an easy interface to the node from Python
    scripts.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 8-10
    :emphasize-lines: 2

.. _ogn_keyword_node_icon:
.. rubric:: icon

A string value that represents the path, relative to the .ogn file, of the icon file that represents the node. This
icon should be a square SVG file. If not specified then it will default to the file with the same name as the *.ogn*
file with the *.svg* extension (e.g. *OgnMyNode.ogn* looks for the file *OgnMyNode.svg*). When no icon file exists the
UI can choose a default for it. The icon will be installed into the extension's generated *ogn/* directory

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 85-87
    :dedent: 4
    :emphasize-lines: 2

The extended syntax for the icon description adds the ability to specify custom coloring. Instead of just a string path,
the icon is represented by a dictionary of icon properties. Allowed values are **"path"**, the icon location as with
the simple syntax, **"color"**, a color representation for the draw part of the icon's shape, **"backgroundColor"**,
a color representation for the part of the icon not containing its shape, and **"borderColor"**, a color
representation for the outline of the icon.

Colors are represented in one of two ways - as hexadecimal in the form **#AABBGGRR**, or as a decimal list of
**[R, G, B, A]**, both using the value range [0, 255].

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 90-97
    :dedent: 4
    :emphasize-lines: 2-7

.. note::

    Unspecified colors will use the defaults. An unspecified path will look for the icon in the default location.

.. _ogn_keyword_node_language:
.. rubric:: language

A string value that represents the language of implementation. The default when not specified is **"c++"**. The
other legal value is **"python"**. This value indicates the language in which the node compute algorithm is
written.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 9-11
    :emphasize-lines: 2

.. _ogn_keyword_node_memoryType:
.. rubric:: memoryType

Nodes can be written to work on the CPU, GPU via CUDA, or both. For each case the data access has to take this into
account so that the data comes from the correct memory store. The valid values for the *memoryType* property are
*cpu*, *cuda*, and *any*. The first two mean that by default all attribute values on the node are exclusively in either
CPU or CUDA-specific GPU memory. *any* means that the node could run on either CPU or GPU, where the decision of which
to use happens at runtime. The default value is *cpu*.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 10-12
    :emphasize-lines: 2

.. _ogn_keyword_node_categories:
.. rubric:: categories

Categories provide a way to group similar node types, mostly so that they can be managed easier in the UI.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 305-306
    :emphasize-lines: 2

For a more detailed example see the :ref:`omnigraph_node_categories` "how-to".

.. _ogn_keyword_node_cudaPointers:
.. rubric:: cudaPointers

Usually when the memory type is set to *cuda* or *any* the CUDA memory pointers for array types are returned as a
GPU pointer to GPU data, so when passing the data to CUDA code you have to pass pointers-to-pointers, since the
CPU code cannot dereference them. Sometimes it is more efficient to just pass the GPU pointer directly though,
pointed at by a CPU pointer. (It's still a pointer to allow for null values.) You can do this by specifying *"cpu"*
as your *cudaPointers* property.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 230-234
    :emphasize-lines: 4

.. note::

    You can also specify *"cuda"* for this value, although as it is the default this has no effect.

.. _ogn_keyword_node_metadata:
.. rubric:: metadata

Node types can have key/value style metadata attached to them by adding a dictionary of them using the *metadata*
property. The key and value are any arbitrary string, though it's a good idea to avoid keywords starting with
with underscore (**_**) as they may have special meaning to the graph. Lists of strings can also be used as metadata
values, though they will be transformed into a single comma-separated string.

A simple example of useful metadata is a human readable format for your node type name. UI code can then read the
consistently named metadata to provide a better name in any interface requiring node type selection. In the example
the keyword *author* is used.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 11-15
    :emphasize-lines: 2-4

.. tip::

    There are several hardcoded metadata values, described in this guide. The keywords under which these are stored
    are available as constants for consistency, and can be found in Python in the og.MetadataKeys object and in C++
    in the file *omni/graph/core/ogn/Database.h*.

.. _ogn_keyword_node_scheduling:
.. rubric:: scheduling

A string or list of string values that represent information for the scheduler on how nodes of this type may be safely
scheduled. The string values are fixed, and say specific things about the kind of data the node access when
computing.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 182-184
    :emphasize-lines: 2

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 187-189
    :emphasize-lines: 2

The strings accepted as values in the .ogn file are described below (extracted directly from the code)

.. literalinclude:: ../../../../source/extensions/omni.graph.tools/python/_impl/node_generator/parse_scheduling.py
    :language: python
    :start-after: begin-scheduling-hints
    :end-before: end-scheduling-hints

.. _ogn_keyword_node_singleton:
.. rubric:: singleton

**singleton** is metadata with special meaning to the node type, so as a shortcut it can also be specified as its own
keyword at the node level. The meaning is the same; associate a piece of metadata with the node type. This piece of
metadata indicates the quality of the node type of only being able to instantiate a single node of that type in a graph
or its child graphs. The value is specified as a boolean, though it is stored as the string "1". (If the boolean is
false then nothing is stored, as that is the default.)

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 111-113
    :emphasize-lines: 2
    :dedent: 4

.. _ogn_keyword_node_tags:
.. rubric:: tags

**tags** is a very common piece of metadata, so as a shortcut it can also be specified as its own keyword at the
node level. The meaning is the same; associate a piece of metadata with the node type. This piece of
metadata can be used by the UI to better organize sets of nodes into common groups.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 15-17
    :emphasize-lines: 2

.. tip::

    Tags can be either a single string, a comma-separated string, or a list of strings. They will all be represented
    as a comma-separated string in the metadata.

.. _ogn_keyword_node_tokens:
.. rubric:: tokens

Token types are more efficient than string types for comparison, and are fairly common. For that reason the .ogn
file provides this shortcut to predefine some tokens for use in your node implementation code.

The simplest method of adding tokens is to add a single token string.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 12-16
    :emphasize-lines: 4

If you have multiple tokens then you can instead specify a list:

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 71-75
    :emphasize-lines: 4
    :dedent: 4

The lookup is the same:

Lastly, if the token value contains illegal names for C++ or Python variables you can specify tokens in a dictionary,
where the key is the name through which it will be accessed and the value is the actual token string:

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 78-82
    :emphasize-lines: 4
    :dedent: 4

See the :ref:`ogn_user_guide` for information on how to access the different sets of token in your code.

.. _ogn_keyword_node_uiName:
.. rubric:: uiName

**uiName** is a very common piece of metadata, so as a shortcut it can also be specified as its own keyword at the
node level. The meaning is the same; associate a piece of metadata with the node type. This piece of
metadata can be used by the UI to present a more human-readable name for the node type.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 16-17
    :emphasize-lines: 2

.. tip::

    Unlike the actual name, the uiName has no formatting or uniqueness requirements. Choose a name that will make
    its function obvious to a user selecting it from a list.

.. _ogn_attribute_dictionaries:

Attribute Dictionaries
----------------------
Each of the three attribute sections, denoted by the keywords `inputs`, `outputs`, and `state`, contain a list of
attributes of each respective location and their properties.

:**inputs**:
    Attributes that are read-only within the node's compute function. These form the collection of data used to run
    the node's computation algorithm.

:**outputs**:
    Attributes whose values are generated as part of the computation algorithm. Until the node computes their values
    they will be undefined. This data is passed on to other nodes in the graph, or made available for inspection.

:**state**:
        Attributes that persist between one evaluation and the next. They are both readable and writable. The primary
        difference between **state** attributes and **output** attributes is that when you set the value on a **state**
        attribute that value is guaranteed to be there the next time the node computes. Its data is entirely owned by
        the node.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 19-25
    :emphasize-lines: 2,4,6
    :dedent: 4

.. note::

    If there are no attributes of a specific location then that section can simply be omitted.

.. _ogn_attribute_property_keywords:

Attribute Property Keywords
---------------------------
The top level keyword of the attribute is always the unique name. It is always namespaced within the section it
resides and only need be unique within that section. For example, the attribute ``mesh`` can appear in both the
``inputs`` and ``outputs`` sections, where it will be named ``inputs:mesh`` and ``outputs:mesh`` respectively.

Attribute Properties
++++++++++++++++++++
Like the outer node level, each of the attributes has a set of mandatory and optional attributes.

.. _ogn_keyword_attribute_description:
.. rubric:: description

As with the node, the *description* field is a multi-line description of the attribute, optionally with reStructuredText
formatting. The description should contain enough information for the user to know how that attribute will be used
(as an input), computed (as an output), or updated (as state).

.. tip::

    This mandatory string should inform users exactly what data the attribute contains, as concisely as possible.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 27-30
    :emphasize-lines: 3

.. _ogn_keyword_attribute_type:
.. rubric:: type

The *type* property is one of several hard-coded values that specify what type of data the attribute contains. As we
ramp up not all type combinations are supported; run `generate_node.py --help` to see the currently supported list
of attribute types. For a full list of supported types and the data types they generate see :ref:`ogn_attribute_types`.

.. tip::

    This field is mandatory, and will help determine what type of interface is generated for the node.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 28-31
    :emphasize-lines: 3

.. _ogn_keyword_attribute_default:
.. rubric:: default

The *default* property on inputs contains the value of the attribute that will be used when the user has not explicitly
set a value or provided an incoming connection to it. For outputs the default value is optional and will only be used
when the node compute method cannot be run.

The value type of the *default* property will be the JSON version of the type of data, shown in
:ref:`ogn_attribute_types`.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 30-32
    :emphasize-lines: 2

.. tip::

    Although input attributes should all have a default, concrete data types need not have a default set if the intent
    is for them to have their natural default. It will be assigned to them automatically. e.g. 0 for "int",
    [0.0, 0.0, 0.0] for "float[3]", false for "bool", and "[]" for any array types.

.. warning::

    Some attribute types, such as "any" and "bundle", have no well-defined data types and cannot have a default set.

.. _ogn_keyword_attribute_deprecated:
.. rubric:: deprecated

The *deprecated* property is used to indicate that the attribute is being phased out and should no longer be used.
The value of the property is a string or array of strings providing users with information on
how they should change their graphs to accommodate the eventual removal of the attribute.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 272-289
    :emphasize-lines: 7,14-17

.. _ogn_keyword_attribute_optional:
.. rubric:: optional

The *optional* property is used to tell the node whether the attribute's value needs to be present in order for the
compute function to run. If it is set to `true` then the value is not checked before calling compute. The default
value `false` will not call the compute function if the attribute does not have a valid value.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 31-33
    :emphasize-lines: 2

.. _ogn_keyword_attribute_memoryType:
.. rubric:: memoryType

By default every attribute in a node will use the *memoryType* defined
:ref:`at the node level<ogn_keyword_node_memoryType>`. It's possible for attributes
to override that choice by adding that same keyword in the attribute properties.

Here's an example of an attribute that overrides the node level memory type to force the attribute onto
the CPU. You might do this to keep cheap POD values on the CPU while the expensive data arrays go directly to the GPU.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 32-34
    :emphasize-lines: 2

.. _ogn_keyword_attribute_range:
.. rubric:: minimum/maximum

When specified, these properties represent the minimum and maximum allowable value for the attribute. For arrays the
values are applicable to every array element. For tuples the values will themselves be tuples with the same size.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 33-36
    :emphasize-lines: 2-3

.. note::

    These properties are only valid for the numeric attribute types, including tuples and arrays.
    At present they are not applied at runtime, only for validating test and default values within the .ogn file,
    however in the future they may be saved so it is always a good idea to specify values here when applicable.

.. _ogn_keyword_attribute_metadata:
.. rubric:: metadata

Attributes can also have key/value style metadata attached to them by adding a dictionary of them using the
*metadata* property. The key and value are any arbitrary string, though it's a good idea to avoid keywords starting
with underscore (**_**) as they may have special meaning to the graph. Lists of strings can also be used as metadata
values, though they will be transformed into a single comma-separated string.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 35-39
    :emphasize-lines: 2-4

There are a number of attribute metadata keys with special meanings:

=============   ====
allowedTokens   Used only for attributes of type *token* and contains a list of the values that token is allowed to take.

                .. literalinclude:: ogn_example.json
                    :language: json
                    :lines: 192-200
                    :emphasize-lines: 5-7

                Sometimes you may wish to have special characters in the list of allowed tokens. The generated code uses the token
                name for easy access to its values so in these cases you will have to also supply a corresponding safe name for the
                token value through which the generated code will access it.

                .. literalinclude:: ogn_example.json
                    :language: json
                    :lines: 203-215
                    :emphasize-lines: 5-11

                In both cases you would access the token values through the database members ``db.tokens.lt``,
                ``db.tokens.gt``, and ``db.tokens.ne``.

hidden          This is a hint to the application that the attribute should be hidden from the user.

                .. literalinclude:: ogn_example.json
                    :language: json
                    :lines: 248-257
                    :emphasize-lines: 6-8

                Less commonly used attributes are often hidden to declutter the UI and the application may provide a
                mechanism to allow the user to display them on request. For example, in the Create application hidden
                attributes are not displayed in its Graph windows but do appear in its Property window from where their
                hidden state can be toggled off and on.

internal        Marks an attribute which is for internal use only. An application would not normally display the
                attribute to users or allow them to interact with it through its UI.

                .. literalinclude:: ogn_example.json
                    :language: json
                    :lines: 260-269
                    :emphasize-lines: 6-8

literalOnly     Indicates that the value of the attribute can only be set to a literal. In other words, if an attribute
                has **literalOnly** set to 1, then it cannot be connected to other attributes, so the only way to modify
                the value of the attribute is to set its value to a literal. A typical use case is the input attributes
                of event source nodes. Since the action evaluator does not evaluate nodes upstream of an event source
                node, the input attributes of event source nodes should not be allowed to connect to upstream nodes, so
                they should be declared as **literalOnly**.

                .. literalinclude:: ogn_example.json
                    :language: json
                    :lines: 237-245
                    :emphasize-lines: 5-7

outputOnly      Used with an input attribute which can be the source of output connections but should not be the
                target of input connections. Typically an application will allow input attributes to take their value
                from an incoming connection or to be set by the user through the UI if they don't have an incoming
                connection. The application may also disallow outbound connections. Setting **outputOnly** to 1 is a
                hint to the application that it should continue to allow the user to set the attribute's value through
                its UI but disallow incoming connections and enable outgoing connections. A typical use for this is with
                a "constant" node which allows the user to enter a constant value which can then be passed on to other
                nodes via output connections.

                .. literalinclude:: ogn_example.json
                    :language: json
                    :lines: 218-227
                    :emphasize-lines: 6-8
=============   ====

.. _ogn_keyword_attribute_uiName:
.. rubric:: uiName

**uiName** is a very common piece of metadata, so as a shortcut it can also be specified as its own keyword at the
attribute level. The meaning is the same; associate a piece of metadata with the attribute. This piece of
metadata can be used by the UI to present a more human-readable name for the attribute.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 37-40
    :emphasize-lines: 3

.. tip::

    Unlike the actual name, the uiName has no formatting or uniqueness requirements. Choose a name that will make
    its function obvious to a user selecting it from a list. The UI may or may not include the namespace when
    displaying it so if that distinction is critical, include it in the uiName.

.. _ogn_keyword_attribute_uiType:
.. rubric:: uiType

**uiType** is used to provide a hint to the property panel as to how the property should bre displayed.  When "filePath"
is specified, string and token fields will create file browser widgets in the property panel.  When "color" is
specified, 3- and 4-component tuples will use a color picker widget in the property panel.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 298-300
    :emphasize-lines: 1

.. _ogn_keyword_attribute_unvalidated:
.. rubric:: unvalidated

**unvalidated** is similar to the **optional** keyword, in that it is used to tag attributes that may not take part
in a ``compute()``. The difference is that these attributes will always exists, they just may not have valid data
when the compute is invoked. For such attributes the onus is on the node writer to check validity of such attributes
if they do end up being used for the compute.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 164-179
    :emphasize-lines: 9,14
    :dedent: 4

.. _ogn_test_data:

Test Definitions
----------------

The node generator is also capable of automatically generating some unit tests on the operation of the node's
algorithm through the **tests** property. This property contains a list of dictionaries, where each entry in the
list is a dictionary of `attribute name : attribute value`.

The test runs by setting all of the input attributes to their corresponding values in the dictionary, executing the
node's compute algorithm, and then comparing the computed values of the outputs against their corrsponding values in
the dictionary.

.. note::

  When input attributes do not have a value in the tests their default is used. When output attributes do not have a
  value in the test they are not checked against the computed result.

There are two methods of specifying test data. They are equivalent so you can use the one that makes the most sense
for your particular test cases. They can coexist if you have different types of test data.

The first method is using a single dictionary to specify any non-default attribute values.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 44-47
    :emphasize-lines: 2-3

This example shows test cases to exercise a simple node that adds two integers together. The first test says *if the
node has inputs 1 and 2 the output should be 3* and the second one says *if the node has an input of 5 and a default
valued input the output should be 5* (the defaults have been set to 0).

For a more complex text you can specify the data involved in the test by location instead of all in a single
dictionary. Here's a similar example for an 8 dimensional polynomial solver.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 46-61
    :emphasize-lines: 2-15

CPU/GPU Data Switch
+++++++++++++++++++
There is one special piece of test configuration that applies when you have output data that switches at runtime
between CPU and GPU (usually through some sort of input information, such as a boolean switch, or a limit on data
size). This information tells the test generator that an output should be expected on the GPU instead of the default
CPU location.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 61-67
    :emphasize-lines: 6

This example illustrates testing of an output on GPU, where the GPU location is selected at runtime based on the
attribute *inputs:isGpu*.

Extended Type Test Data
+++++++++++++++++++++++
If your node has extended-type attributes, you will have to specify which type you want to use for your test. This is
necessary to distinguish between types which aren't support by json. For example double, float and half.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 68-72
    :emphasize-lines: 3-4

This example has one input "multiplier" which is a specific decimal type, input "element" and output "tuple" which
are extended-types. "element" and "tuple" are related by the logic of the node in that their base types must match, so
the test is specifying the same type for those attributes.

For tests that deal with extended data types you must also specify the data type with the value to be set so that it
can properly resolve. (The other way of resolving data types is by connection. These simple tests only involve a single
node so resolution can only be done by setting values directly.)

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 105-108
    :emphasize-lines: 2-3

State Test Data
+++++++++++++++
In the special case of tests that need to exercise state data extra syntax is added to differentiate between values
that should be set on state attributes before the test starts and values that are checked on them after the test is
completed. The special suffix *_set* is appended to the state namespace to signify that a value is to be initialized
before a test runs. You may optionally add the suffix *_get* to the state namespace to clarify which values are to be
checked after the test runs but that is the default so it is not necessary.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 116-135
    :emphasize-lines: 2-19

Test Graph Setup
++++++++++++++++
For more complex situations you may need more than just a single node to test code paths properly. For these situations
there is a pre-test setup section you can add, in the form of the :ref:`Controller.edit<ogn_omnigraph_controller>`
function parameters. Only the creation directives are accepted, not the destructive ones such as *disconnections*.

These creation directives are all executed by the test script before it starts to run, providing you with a known
starting graph configuration consisting of any nodes, prims, and connections needed to run the test.

.. literalinclude:: ogn_example.json
    :language: json
    :lines: 138-162
    :emphasize-lines: 9-23

.. note::

    If you define the graph in this way then the first node in your *"nodes"* directives must refer to the node
    being tested. If there is no graph specified then a single node of the type being tested will be the sole
    contents of the stage when running the test.

Simplified Schema
=================

This schema outlines the relationships between all of the values in the .ogn file. It is simplified in that it does
not include schema information that validates data types in *default*, *minimum*, *maximum*, and test section fields.
(It's possible to include such information in a schema, it just makes it very difficult to follow.)

.. literalinclude:: ogn_schema.json
    :linenos:
    :language: json
