Repository: common-workflow-language/cwltool

Issue:
CommandLineTool.arguments: string interpolation with `$(self)` incorrectly fails
According to https://www.commonwl.org/v1.0/CommandLineTool.html#Parameter_references
If a parameter reference is allowed in a field, then `self` is allowed; it should be `null` if not specifically defined.

`self-dump.cwl`
``` cwl
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: CommandLineTool
inputs:
  a_string:
    type: string
    default: z
baseCommand: echo
arguments:
 - '{"self":$(self)}'
stdout: self.json
outputs:
  self_dump: stdout
```

```
$ cwltool self-dump.cwl 
/home/mcrusoe/cwltool/env3/bin/cwltool 1.0.20180528123027
Resolved 'self-dump.cwl' to 'file:///home/mcrusoe/cwltool/self-dump.cwl'
Workflow error, try again with --debug for more information:
self-dump.cwl:10:4: Expression evaluation error:
                    Syntax error in parameter reference 'self': self is not defined. This could be
                    due to using Javascript code without specifying InlineJavascriptRequirement.
```
Expected output: that `self.json` would contain `{"self": null}`


Discussion:

Resolving patch:
diff --git a/cwltool/expression.py b/cwltool/expression.py
--- a/cwltool/expression.py
+++ b/cwltool/expression.py
@@ -217,7 +217,7 @@ def evaluator(
         if first_symbol_end + 1 == len(ex) and first_symbol == "null":
             return None
         try:
-            if obj.get(first_symbol) is None:
+            if first_symbol not in obj:
                 raise WorkflowException("%s is not defined" % first_symbol)
 
             return next_seg(


Test patch:
diff --git a/tests/test_examples.py b/tests/test_examples.py
--- a/tests/test_examples.py
+++ b/tests/test_examples.py
@@ -1414,3 +1414,16 @@ def test_malformed_reqs() -> None:
         match=r".*wc-tool-bad-reqs\.cwl:6:1: If 'requirements' is\s*present\s*then\s*it\s*must\s*be\s*a\s*list.*",
     ):
         factory.make(get_data("tests/wc-tool-bad-reqs.cwl"))
+
+
+def test_arguments_self() -> None:
+    """Confirm that $(self) works in the arguments list."""
+    factory = cwltool.factory.Factory()
+    check = factory.make(get_data("tests/wf/paramref_arguments_self.cwl"))
+    outputs = cast(Dict[str, Any], check())
+    assert "self_review" in outputs
+    assert len(outputs) == 1
+    assert (
+        outputs["self_review"]["checksum"]
+        == "sha1$724ba28f4a9a1b472057ff99511ed393a45552e1"
+    )
diff --git a/tests/wf/paramref_arguments_self.cwl b/tests/wf/paramref_arguments_self.cwl
new file mode 100644
--- /dev/null
+++ b/tests/wf/paramref_arguments_self.cwl
@@ -0,0 +1,41 @@
+#!/usr/bin/env cwl-runner
+cwlVersion: v1.0
+class: Workflow
+inputs: []
+outputs:
+  self_review:
+    type: File
+    outputSource: evaluate_self/self_review
+steps:
+  dump_self:
+    run:
+      class: CommandLineTool
+      baseCommand: echo
+      inputs: []
+      arguments:
+       - '{"self":$(self)}'
+      stdout: self.json
+      outputs:
+        self_json: stdout
+    in: []
+    out: [self_json]
+  evaluate_self:
+    run:
+      class: CommandLineTool
+      hints:
+        DockerRequirement:
+          dockerPull: everpeace/curl-jq
+      inputs:
+        self:
+          type: File
+          inputBinding:
+            position: 2
+      stdout: self_review.txt
+      outputs:
+        self_review: stdout
+      baseCommand: jq
+      arguments:
+       - valueFrom: '.self | type == "null"'
+         position: 1
+    in: { self: dump_self/self_json }
+    out: [ self_review ]