Motivation ========== Avocado creates a tree like object to represent its parameters coming from the varianter. But that tree object can be accessed only by INSTRUMENTED tests. When it comes to non-INSTRUMENTED tests, test writers have to rely on the environment variables created out of that tree structure. The translation from tree object to environment variables has some caveats currently and that's the main focus of this RFC.
Reference: https://trello.com/c/4cNAKW6I/1111-discuss-a-way-to-control-the-export-of-parameters-as-environment-variables Currently, the tree object is flattened, creating environment variables with the names of the leaves, disregarding the branch path and also overwriting preexisting environment variables with the same name. Example: $ cat parameters.yaml branch1: foo: bar1 branch2: foo: bar2 With the above yaml file, avocado will generate the following tree: $ avocado variants -m parameters.yaml --tree -c Multiplex tree representation: ┗━━ run ┣━━ branch1 ┃ → foo: bar1 ┗━━ branch2 → foo: bar2 Even though two parameters have the same name, they are in different branches and have different values. Both parameters can be accessed in INSTRUMENTED tests using: self.params.get('foo', path='/run/branch1/*') and self.params.get('foo', path='/run/branch2/*') When it comes to non-INSTRUMENTED tests, i.e. SIMPLE tests, the tree is flattened and the corresponding environment variables are created. In the same example above, a bash script which used the "foo" parameter above would look like this: #!/bin/bash echo ${foo} But since we don't use the path information, the $foo is the last parameter with that name from the tree. The previous "foo" value will not be available. And, as mentioned before, a previous environment variable with that name will be overwritten, with obvious consequences. Proposal ======== To avoid parameters collision, one option is to use the path information to create the environment variable name. In the example above, instead of one "foo" variable, we would create a "run_branch1_foo" containing "bar1" and a "run_branch2_foo" containing "bar2". To avoid overwriting the preexisting environment variables, one option is create a more unique variable name, including the "AVOCADO_" string at the beginning. The same example above would then become "AVOCADO_run_branch1_foo" and "AVOCADO_run_branch2_foo", with their respective values. The proposal above would improve the situation, while keeping the current user experience, enabling more powerful parameters API for non-INSTRUMENTED tests. Besides the proposals above, one extra feature that we have to consider is to create an environment variable with a machine-parsable content with the serialized varianter object. A good format for that would be JSON, a text format that is completely language independent but uses conventions that are familiar to programmers, which is already used by Avocado to serialize the varianter object in the 'jobdata' module. With that in mind, using the same example, the proposal is to create a variable called "AVOCADO_PARAMETERS" containing: [{"paths": ["/run/*"], "variant": [["/run/first_branch", [["/run/first_branch", "foo", "bar1"]]], ["/run/second_branch", [["/run/second_branch", "foo", "bar2"]]]], "variant_id": "first_branch-second_branch-4cd9"}] That structure would be easily parsed/used by tests written in any language. Note: As an additional resource, we could make public a Python API for loading that serialized structure back in a variant object, so Python users would have the same experience as in INSTRUMENTED tests when writing non-INSTRUMENTED Python tests. Expected Results ================ Mitigate the cases where the parameters can not be accessed by non-INSTRUMENTED tests and avoid collision with preexisting environment variables. Looking forward to read your comments. -- apahim
