Allow JSON to be Input from a File (#1175)
- Pass JSON files to parameters and annotations
- Refactor parameter and annotation handling
- Use KeyValueArr data type to store annotations and parameters
- Refactor summaries for get commands
- Use KeyValueArr data type to get annotations and parameters
- Refactor parameter and annotation tests
- Order of params and annots are not guaranteed in Go map data structures
- Fixes: #426
diff --git a/tests/src/common/Wsk.scala b/tests/src/common/Wsk.scala
index ede51db..c125a71 100644
--- a/tests/src/common/Wsk.scala
+++ b/tests/src/common/Wsk.scala
@@ -225,6 +225,8 @@
kind: Option[String] = None, // one of docker, copy, sequence or none for autoselect else an explicit type
parameters: Map[String, JsValue] = Map(),
annotations: Map[String, JsValue] = Map(),
+ parameterFile: Option[String] = None,
+ annotationFile: Option[String] = None,
timeout: Option[Duration] = None,
memory: Option[ByteSize] = None,
logsize: Option[ByteSize] = None,
@@ -242,6 +244,8 @@
} ++
{ parameters flatMap { p => Seq("-p", p._1, p._2.compactPrint) } } ++
{ annotations flatMap { p => Seq("-a", p._1, p._2.compactPrint) } } ++
+ { parameterFile map { pf => Seq("-P", pf) } getOrElse Seq() } ++
+ { annotationFile map { af => Seq("-A", af) } getOrElse Seq() } ++
{ timeout map { t => Seq("-t", t.toMillis.toString) } getOrElse Seq() } ++
{ memory map { m => Seq("-m", m.toMB.toString) } getOrElse Seq() } ++
{ logsize map { l => Seq("-l", l.toMB.toString) } getOrElse Seq() } ++
@@ -259,12 +263,14 @@
def invoke(
name: String,
parameters: Map[String, JsValue] = Map(),
+ parameterFile: Option[String] = None,
blocking: Boolean = false,
result: Boolean = false,
expectedExitCode: Int = SUCCESS_EXIT)(
implicit wp: WskProps): RunResult = {
val params = Seq(noun, "invoke", "--auth", wp.authKey, fqn(name)) ++
{ parameters flatMap { p => Seq("-p", p._1, p._2.compactPrint) } } ++
+ { parameterFile map { pf => Seq("-P", pf) } getOrElse Seq() } ++
{ if (blocking) Seq("--blocking") else Seq() } ++
{ if (result) Seq("--result") else Seq() }
cli(wp.overrides ++ params, expectedExitCode)
@@ -290,6 +296,8 @@
name: String,
parameters: Map[String, JsValue] = Map(),
annotations: Map[String, JsValue] = Map(),
+ parameterFile: Option[String] = None,
+ annotationFile: Option[String] = None,
feed: Option[String] = None,
shared: Option[Boolean] = None,
update: Boolean = false,
@@ -299,6 +307,8 @@
{ feed map { f => Seq("--feed", fqn(f)) } getOrElse Seq() } ++
{ parameters flatMap { p => Seq("-p", p._1, p._2.compactPrint) } } ++
{ annotations flatMap { p => Seq("-a", p._1, p._2.compactPrint) } } ++
+ { parameterFile map { pf => Seq("-P", pf) } getOrElse Seq() } ++
+ { annotationFile map { af => Seq("-A", af) } getOrElse Seq() } ++
{ shared map { s => Seq("--shared", if (s) "yes" else "no") } getOrElse Seq() }
cli(wp.overrides ++ params, expectedExitCode)
}
@@ -313,10 +323,12 @@
def fire(
name: String,
parameters: Map[String, JsValue] = Map(),
+ parameterFile: Option[String] = None,
expectedExitCode: Int = SUCCESS_EXIT)(
implicit wp: WskProps): RunResult = {
val params = Seq(noun, "fire", "--auth", wp.authKey, fqn(name)) ++
- { parameters flatMap { p => Seq("-p", p._1, p._2.compactPrint) } }
+ { parameters flatMap { p => Seq("-p", p._1, p._2.compactPrint) } } ++
+ { parameterFile map { pf => Seq("-P", pf) } getOrElse Seq() }
cli(wp.overrides ++ params, expectedExitCode)
}
}
@@ -650,6 +662,8 @@
name: String,
parameters: Map[String, JsValue] = Map(),
annotations: Map[String, JsValue] = Map(),
+ parameterFile: Option[String] = None,
+ annotationFile: Option[String] = None,
shared: Option[Boolean] = None,
update: Boolean = false,
expectedExitCode: Int = SUCCESS_EXIT)(
@@ -657,6 +671,8 @@
val params = Seq(noun, if (!update) "create" else "update", "--auth", wp.authKey, fqn(name)) ++
{ parameters flatMap { p => Seq("-p", p._1, p._2.compactPrint) } } ++
{ annotations flatMap { p => Seq("-a", p._1, p._2.compactPrint) } } ++
+ { parameterFile map { pf => Seq("-P", pf) } getOrElse Seq() } ++
+ { annotationFile map { af => Seq("-A", af) } getOrElse Seq() } ++
{ shared map { s => Seq("--shared", if (s) "yes" else "no") } getOrElse Seq() }
cli(wp.overrides ++ params, expectedExitCode)
}
diff --git a/tests/src/system/basic/WskBasicTests.scala b/tests/src/system/basic/WskBasicTests.scala
index 36886e9..24492e9 100644
--- a/tests/src/system/basic/WskBasicTests.scala
+++ b/tests/src/system/basic/WskBasicTests.scala
@@ -238,6 +238,26 @@
}
}
+ it should "create, and invoke an action using a parameter file" in withAssetCleaner(wskprops) {
+ val name = "paramFileAction"
+ val file = Some(TestUtils.getTestActionFilename("argCheck.js"))
+ val argInput = Some(TestUtils.getTestActionFilename("validInput2.json"))
+
+ (wp, assetHelper) =>
+ assetHelper.withCleaner(wsk.action, name) {
+ (action, _) => action.create(name, file)
+ }
+
+ val expectedOutput = JsObject(
+ "payload" -> JsString("test")
+ )
+ val run = wsk.action.invoke(name, parameterFile = argInput)
+ withActivation(wsk.activation, run) {
+ activation =>
+ activation.response.result shouldBe Some(expectedOutput)
+ }
+ }
+
/**
* Tests creating an action from a malformed js file. This should fail in
* some way - preferably when trying to create the action. If not, then
@@ -394,6 +414,27 @@
res.stdout should include regex(s"ok: created trigger $name")
}
+ it should "create, and fire a trigger using a parameter file" in withAssetCleaner(wskprops) {
+ val name = "paramFileTrigger"
+ val file = Some(TestUtils.getTestActionFilename("argCheck.js"))
+ val argInput = Some(TestUtils.getTestActionFilename("validInput2.json"))
+
+ (wp, assetHelper) =>
+ assetHelper.withCleaner(wsk.trigger, name) {
+ (trigger, _) =>
+ trigger.create(name)
+ }
+
+ val expectedOutput = JsObject(
+ "payload" -> JsString("test")
+ )
+ val run = wsk.trigger.fire(name, parameterFile = argInput)
+ withActivation(wsk.activation, run) {
+ activation =>
+ activation.response.result shouldBe Some(expectedOutput)
+ }
+ }
+
behavior of "Wsk Rule CLI"
it should "create rule, get rule, update rule and list rule" in withAssetCleaner(wskprops) {
diff --git a/tests/src/whisk/core/cli/test/JsonArgsForTests.scala b/tests/src/whisk/core/cli/test/JsonArgsForTests.scala
index e2cf23b..4e41b85 100644
--- a/tests/src/whisk/core/cli/test/JsonArgsForTests.scala
+++ b/tests/src/whisk/core/cli/test/JsonArgsForTests.scala
@@ -24,42 +24,86 @@
object JsonArgsForTests {
- def getEscapedJSONTestArgInput(parameters: Boolean = true) = Seq(
- if (parameters) "-p" else "-a",
- "\"key\"with\\escapes", // key: key"with\escapes (will be converted to JSON string "key\"with\\escapes")
- "{\"valid\": \"JSON\"}", // value: {"valid":"JSON"}
- if (parameters) "-p" else "-a",
- "another\"escape\"", // key: another"escape" (will be converted to JSON string "another\"escape\"")
- "{\"valid\": \"\\nJ\\rO\\tS\\bN\\f\"}", // value: {"valid":"\nJ\rO\tS\bN\f"} JSON strings can escape: \n, \r, \t, \b, \f
- // NOTE: When uncommentting these tests, be sure to include the expected response in getEscapedJSONTestArgOutput()
- // if (parameters) "-p" else "-a",
- // "escape\\again", // key: escape\again (will be converted to JSON string "escape\\again")
- // "{\"valid\": \"JS\\u2312ON\"}", // value: {"valid":"JS\u2312ON"} JSON strings can have escaped 4 digit unicode
- // if (parameters) "-p" else "-a",
- // "mykey", // key: mykey (will be converted to JSON string "key")
- // "{\"valid\": \"JS\\/ON\"}", // value: {"valid":"JS\/ON"} JSON strings can have escaped \/
- if (parameters) "-p" else "-a",
- "key1", // key: key (will be converted to JSON string "key")
- "{\"nonascii\": \"日本語\"}", // value: {"nonascii":"日本語"} JSON strings can have non-ascii
- if (parameters) "-p" else "-a",
- "key2", // key: key (will be converted to JSON string "key")
- "{\"valid\": \"J\\\\SO\\\"N\"}" // value: {"valid":"J\\SO\"N"} JSON strings can have escaped \\ and \"
+ def getInvalidJSONInput = Seq(
+ "{\"invalid1\": }",
+ "{\"invalid2\": bogus}",
+ "{\"invalid1\": \"aKey\"",
+ "invalid \"string\"",
+ "{\"invalid1\": [1, 2, \"invalid\"\"arr\"]}"
+ )
+
+ def getJSONFileOutput() = JsArray(
+ JsObject(
+ "key" -> JsString("a key"),
+ "value" -> JsString("a value")
+ ),
+ JsObject(
+ "key" -> JsString("a bool"),
+ "value" -> JsBoolean(true)
+ ),
+ JsObject(
+ "key" -> JsString("objKey"),
+ "value" -> JsObject(
+ "b" -> JsString("c")
+ )
+ ),
+ JsObject(
+ "key" -> JsString("objKey2"),
+ "value" -> JsObject(
+ "another object" -> JsObject(
+ "some string" -> JsString("1111")
+ )
+ )
+ ),
+ JsObject(
+ "key" -> JsString("objKey3"),
+ "value" -> JsObject(
+ "json object" -> JsObject(
+ "some int" -> JsNumber(1111)
+ )
+ )
+ ),
+ JsObject(
+ "key" -> JsString("a number arr"),
+ "value" -> JsArray(
+ JsNumber(1), JsNumber(2), JsNumber(3)
+ )
+ ),
+ JsObject(
+ "key" -> JsString("a string arr"),
+ "value" -> JsArray(
+ JsString("1"), JsString("2"), JsString("3")
+ )
+ ),
+ JsObject(
+ "key" -> JsString("a bool arr"),
+ "value" -> JsArray(
+ JsBoolean(true), JsBoolean(false), JsBoolean(true)
+ )
+ ),
+ JsObject(
+ "key" -> JsString("strThatLooksLikeJSON"),
+ "value" -> JsString("{\"someKey\": \"someValue\"}")
+ )
+ )
+
+ def getEscapedJSONTestArgInput() = Map(
+ "key1" -> JsObject(
+ "nonascii" -> JsString("日本語")
+ ),
+ "key2" -> JsObject(
+ "valid" -> JsString("J\\SO\"N")
+ ),
+ "\"key\"with\\escapes" -> JsObject(
+ "valid" -> JsString("JSON")
+ ),
+ "another\"escape\"" -> JsObject(
+ "valid" -> JsString("\\nJ\\rO\\tS\\bN\\f")
+ )
)
def getEscapedJSONTestArgOutput() = JsArray(
JsObject(
- "key" -> JsString("\"key\"with\\escapes"),
- "value" -> JsObject(
- "valid" -> JsString("JSON")
- )
- ),
- JsObject(
- "key" -> JsString("another\"escape\""),
- "value" -> JsObject(
- "valid" -> JsString("\nJ\rO\tS\bN\f")
- )
- ),
- JsObject(
"key" -> JsString("key1"),
"value" -> JsObject(
"nonascii" -> JsString("日本語")
@@ -70,6 +114,18 @@
"value" -> JsObject(
"valid" -> JsString("J\\SO\"N")
)
+ ),
+ JsObject(
+ "key" -> JsString("\"key\"with\\escapes"),
+ "value" -> JsObject(
+ "valid" -> JsString("JSON")
+ )
+ ),
+ JsObject(
+ "key" -> JsString("another\"escape\""),
+ "value" -> JsObject(
+ "valid" -> JsString("\\nJ\\rO\\tS\\bN\\f")
+ )
)
)
diff --git a/tests/src/whisk/core/cli/test/WskBasicUsageTests.scala b/tests/src/whisk/core/cli/test/WskBasicUsageTests.scala
index 5e6f5f7..f2aa959 100644
--- a/tests/src/whisk/core/cli/test/WskBasicUsageTests.scala
+++ b/tests/src/whisk/core/cli/test/WskBasicUsageTests.scala
@@ -261,68 +261,76 @@
wsk.action.create("updateMissingFile", Some("notfound"), update = true, expectedExitCode = MISUSE_EXIT)
}
- it should "create, and get an action to verify annotation parsing" in withAssetCleaner(wskprops) {
+ it should "create, and get an action to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
val name = "actionAnnotations"
-
val file = Some(TestUtils.getTestActionFilename("hello.js"))
+
assetHelper.withCleaner(wsk.action, name) {
(action, _) =>
- action.create(name, file, annotations = getValidJSONTestArgInput)
+ action.create(name, file, annotations = getValidJSONTestArgInput,
+ parameters = getValidJSONTestArgInput)
}
val stdout = wsk.action.get(name).stdout
assert(stdout.startsWith(s"ok: got action $name\n"))
- wsk.parseJsonString(stdout).fields("annotations") shouldBe getValidJSONTestArgOutput
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create, and get an action to verify parameter parsing" in withAssetCleaner(wskprops) {
+ it should "create, and get an action to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
- val name = "actionParameters"
-
+ val name = "actionAnnotAndParamParsing"
val file = Some(TestUtils.getTestActionFilename("hello.js"))
+ val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
+
assetHelper.withCleaner(wsk.action, name) {
(action, _) =>
- action.create(name, file, parameters = getValidJSONTestArgInput)
+ action.create(name, file, annotationFile = argInput, parameterFile = argInput)
}
val stdout = wsk.action.get(name).stdout
assert(stdout.startsWith(s"ok: got action $name\n"))
- wsk.parseJsonString(stdout).fields("parameters") shouldBe getValidJSONTestArgOutput
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create an action with the proper parameter escapes" in withAssetCleaner(wskprops) {
+ it should "create an action with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
- val name = "actionName"
- val file = TestUtils.getTestActionFilename("hello.js")
+ val name = "actionEscapes"
+ val file = Some(TestUtils.getTestActionFilename("hello.js"))
+
assetHelper.withCleaner(wsk.action, name) {
(action, _) =>
- wsk.cli(wskprops.overrides ++ Seq("action", "create", wsk.action.fqn(name), file, "--auth", wp.authKey) ++
- getEscapedJSONTestArgInput())
+ action.create(name, file, parameters = getEscapedJSONTestArgInput,
+ annotations = getEscapedJSONTestArgInput)
}
val stdout = wsk.action.get(name).stdout
assert(stdout.startsWith(s"ok: got action $name\n"))
- wsk.parseJsonString(stdout).fields("parameters") shouldBe getEscapedJSONTestArgOutput
- }
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
- it should "create an action with the proper annotation escapes" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "actionName"
- val file = TestUtils.getTestActionFilename("hello.js")
- assetHelper.withCleaner(wsk.action, name) {
- (action, _) =>
- wsk.cli(wskprops.overrides ++ Seq("action", "create", wsk.action.fqn(name), file, "--auth", wp.authKey) ++
- getEscapedJSONTestArgInput(false))
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
}
-
- val stdout = wsk.action.get(name).stdout
- assert(stdout.startsWith(s"ok: got action $name\n"))
-
- wsk.parseJsonString(stdout).fields("annotations") shouldBe getEscapedJSONTestArgOutput
}
it should "invoke an action that exits during init and get appropriate error" in withAssetCleaner(wskprops) {
@@ -443,96 +451,121 @@
behavior of "Wsk packages"
- it should "create, and get a package to verify annotation parsing" in withAssetCleaner(wskprops) {
+ it should "create, and get a package to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
- val name = "packageAnnotations"
+ val name = "packageAnnotAndParamParsing"
assetHelper.withCleaner(wsk.pkg, name) {
(pkg, _) =>
- pkg.create(name, annotations = getValidJSONTestArgInput)
+ pkg.create(name, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
}
val stdout = wsk.pkg.get(name).stdout
assert(stdout.startsWith(s"ok: got package $name\n"))
- wsk.parseJsonString(stdout).fields("annotations") shouldBe getValidJSONTestArgOutput
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create, and get a package to verify parameter parsing" in withAssetCleaner(wskprops) {
+ it should "create, and get a package to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
- val name = "packageParameters"
+ val name = "packageAnnotAndParamFileParsing"
+ val file = Some(TestUtils.getTestActionFilename("hello.js"))
+ val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
assetHelper.withCleaner(wsk.pkg, name) {
(pkg, _) =>
- pkg.create(name, parameters = getValidJSONTestArgInput)
+ pkg.create(name, annotationFile = argInput, parameterFile = argInput)
}
val stdout = wsk.pkg.get(name).stdout
assert(stdout.startsWith(s"ok: got package $name\n"))
- wsk.parseJsonString(stdout).fields("parameters") shouldBe getValidJSONTestArgOutput
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create a package with the proper parameter escapes" in withAssetCleaner(wskprops) {
+ it should "create a package with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
- val name = "packageName"
+ val name = "packageEscapses"
+
assetHelper.withCleaner(wsk.pkg, name) {
(pkg, _) =>
- wsk.cli(wskprops.overrides ++ Seq("package", "create", wsk.pkg.fqn(name), "--auth", wp.authKey) ++
- getEscapedJSONTestArgInput())
+ pkg.create(name, parameters = getEscapedJSONTestArgInput,
+ annotations = getEscapedJSONTestArgInput)
}
val stdout = wsk.pkg.get(name).stdout
assert(stdout.startsWith(s"ok: got package $name\n"))
- wsk.parseJsonString(stdout).fields("parameters") shouldBe getEscapedJSONTestArgOutput
- }
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
- it should "create an package with the proper annotation escapes" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "packageName"
- assetHelper.withCleaner(wsk.pkg, name) {
- (pkg, _) =>
- wsk.cli(wskprops.overrides ++ Seq("package", "create", wsk.pkg.fqn(name), "--auth", wp.authKey) ++
- getEscapedJSONTestArgInput(false))
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
}
-
- val stdout = wsk.pkg.get(name).stdout
- assert(stdout.startsWith(s"ok: got package $name\n"))
-
- wsk.parseJsonString(stdout).fields("annotations") shouldBe getEscapedJSONTestArgOutput
}
behavior of "Wsk triggers"
- it should "create, and get a trigger to verify annotation parsing" in withAssetCleaner(wskprops) {
+ it should "create, and get a trigger to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
- val name = "triggerAnnotations"
+ val name = "triggerAnnotAndParamParsing"
assetHelper.withCleaner(wsk.trigger, name) {
(trigger, _) =>
- trigger.create(name, annotations = getValidJSONTestArgInput)
+ trigger.create(name, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
}
val stdout = wsk.trigger.get(name).stdout
assert(stdout.startsWith(s"ok: got trigger $name\n"))
- wsk.parseJsonString(stdout).fields("annotations") shouldBe getValidJSONTestArgOutput
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
- it should "create, and get a trigger to verify parameter parsing" in withAssetCleaner(wskprops) {
+ it should "create, and get a trigger to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
- val name = "triggerParameters"
+ val name = "triggerAnnotAndParamFileParsing"
+ val file = Some(TestUtils.getTestActionFilename("hello.js"))
+ val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
assetHelper.withCleaner(wsk.trigger, name) {
(trigger, _) =>
- trigger.create(name, parameters = getValidJSONTestArgInput)
+ trigger.create(name, annotationFile = argInput, parameterFile = argInput)
}
val stdout = wsk.trigger.get(name).stdout
assert(stdout.startsWith(s"ok: got trigger $name\n"))
- wsk.parseJsonString(stdout).fields("parameters") shouldBe getValidJSONTestArgOutput
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
+ }
}
it should "display a trigger summary when --summary flag is used with 'wsk trigger get'" in withAssetCleaner(wskprops) {
@@ -548,34 +581,27 @@
stdout should include regex (s"(?i)trigger\\s+/${ns_regex_list}/${triggerName}")
}
- it should "create a trigger with the proper parameter escapes" in withAssetCleaner(wskprops) {
+ it should "create a trigger with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
- val name = "triggerName"
+ val name = "triggerEscapes"
+
assetHelper.withCleaner(wsk.trigger, name) {
(trigger, _) =>
- wsk.cli(wskprops.overrides ++ Seq("trigger", "create", wsk.trigger.fqn(name), "--auth", wp.authKey) ++
- getEscapedJSONTestArgInput())
+ trigger.create(name, parameters = getEscapedJSONTestArgInput,
+ annotations = getEscapedJSONTestArgInput)
}
val stdout = wsk.trigger.get(name).stdout
assert(stdout.startsWith(s"ok: got trigger $name\n"))
- wsk.parseJsonString(stdout).fields("parameters") shouldBe getEscapedJSONTestArgOutput
- }
+ val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+ val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+ val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
- it should "create a trigger with the proper annotation escapes" in withAssetCleaner(wskprops) {
- (wp, assetHelper) =>
- val name = "triggerName"
- assetHelper.withCleaner(wsk.trigger, name) {
- (trigger, _) =>
- wsk.cli(wskprops.overrides ++ Seq("trigger", "create", wsk.trigger.fqn(name), "--auth", wp.authKey) ++
- getEscapedJSONTestArgInput(false))
+ for (expectedItem <- escapedJSONArr) {
+ receivedParams should contain(expectedItem)
+ receivedAnnots should contain(expectedItem)
}
-
- val stdout = wsk.trigger.get(name).stdout
- assert(stdout.startsWith(s"ok: got trigger $name\n"))
-
- wsk.parseJsonString(stdout).fields("annotations") shouldBe getEscapedJSONTestArgOutput
}
it should "not create a trigger when feed fails to initialize" in withAssetCleaner(wskprops) {
@@ -653,46 +679,179 @@
behavior of "Wsk params and annotations"
- it should "reject commands that are executed with params or annot that are not key/value pairs" in {
+ it should "reject commands that are executed with invalid JSON for annotations and parameters" in {
+ val invalidJSONInputs = getInvalidJSONInput
+ val invalidJSONFiles = Seq(
+ TestUtils.getTestActionFilename("malformed.js"),
+ TestUtils.getTestActionFilename("invalidInput1.json"),
+ TestUtils.getTestActionFilename("invalidInput2.json"),
+ TestUtils.getTestActionFilename("invalidInput3.json"),
+ TestUtils.getTestActionFilename("invalidInput4.json")
+ )
+ val paramCmds = Seq(
+ Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js")),
+ Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js")),
+ Seq("action", "invoke", "actionName"),
+ Seq("package", "create", "packageName"),
+ Seq("package", "update", "packageName"),
+ Seq("package", "bind", "packageName", "boundPackageName"),
+ Seq("trigger", "create", "triggerName"),
+ Seq("trigger", "update", "triggerName"),
+ Seq("trigger", "fire", "triggerName")
+ )
+ val annotCmds = Seq(
+ Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js")),
+ Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js")),
+ Seq("package", "create", "packageName"),
+ Seq("package", "update", "packageName"),
+ Seq("package", "bind", "packageName", "boundPackageName"),
+ Seq("trigger", "create", "triggerName"),
+ Seq("trigger", "update", "triggerName")
+ )
+
+ for (cmd <- paramCmds) {
+ for (invalid <- invalidJSONInputs) {
+ wsk.cli(cmd ++ Seq("-p", "key", invalid), expectedExitCode = ERROR_EXIT)
+ .stderr should include("Invalid parameter argument")
+ }
+
+ for (invalid <- invalidJSONFiles) {
+ wsk.cli(cmd ++ Seq("-P", invalid), expectedExitCode = ERROR_EXIT)
+ .stderr should include("Invalid parameter argument")
+
+ }
+ }
+
+ for (cmd <- annotCmds) {
+ for (invalid <- invalidJSONInputs) {
+ wsk.cli(cmd ++ Seq("-a", "key", invalid), expectedExitCode = ERROR_EXIT)
+ .stderr should include("Invalid annotation argument")
+ }
+
+ for (invalid <- invalidJSONFiles) {
+ wsk.cli(cmd ++ Seq("-A", invalid), expectedExitCode = ERROR_EXIT)
+ .stderr should include("Invalid annotation argument")
+ }
+ }
+ }
+
+ it should "reject commands that are executed with a missing or invalid parameter or annotation file" in {
+ val emptyFile = TestUtils.getTestActionFilename("emtpy.js")
+ val missingFile = "notafile"
+ val emptyFileMsg = s"File '$emptyFile' is not a valid file or it does not exist"
+ val missingFileMsg = s"File '$missingFile' is not a valid file or it does not exist"
+ val invalidArgs = Seq(
+ (Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
+ emptyFileMsg),
+ (Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
+ emptyFileMsg),
+ (Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
+ (Seq("action", "create", "actionName", "-P", emptyFile), emptyFileMsg),
+ (Seq("action", "update", "actionName", "-P", emptyFile), emptyFileMsg),
+ (Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
+ (Seq("package", "create", "packageName", "-P", emptyFile), emptyFileMsg),
+ (Seq("package", "update", "packageName", "-P", emptyFile), emptyFileMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-P", emptyFile), emptyFileMsg),
+ (Seq("package", "create", "packageName", "-P", emptyFile), emptyFileMsg),
+ (Seq("package", "update", "packageName", "-P", emptyFile), emptyFileMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-P", emptyFile), emptyFileMsg),
+ (Seq("trigger", "create", "triggerName", "-P", emptyFile), emptyFileMsg),
+ (Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
+ (Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
+ (Seq("trigger", "create", "triggerName", "-P", emptyFile), emptyFileMsg),
+ (Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
+ (Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
+ (Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js"), "-A", missingFile),
+ missingFileMsg),
+ (Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js"), "-A", missingFile),
+ missingFileMsg),
+ (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
+ (Seq("action", "create", "actionName", "-A", missingFile), missingFileMsg),
+ (Seq("action", "update", "actionName", "-A", missingFile), missingFileMsg),
+ (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
+ (Seq("package", "create", "packageName", "-A", missingFile), missingFileMsg),
+ (Seq("package", "update", "packageName", "-A", missingFile), missingFileMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-A", missingFile), missingFileMsg),
+ (Seq("package", "create", "packageName", "-A", missingFile), missingFileMsg),
+ (Seq("package", "update", "packageName", "-A", missingFile), missingFileMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-A", missingFile), missingFileMsg),
+ (Seq("trigger", "create", "triggerName", "-A", missingFile), missingFileMsg),
+ (Seq("trigger", "update", "triggerName", "-A", missingFile), missingFileMsg),
+ (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg),
+ (Seq("trigger", "create", "triggerName", "-A", missingFile), missingFileMsg),
+ (Seq("trigger", "update", "triggerName", "-A", missingFile), missingFileMsg),
+ (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg)
+ )
+
+ invalidArgs foreach {
+ case (cmd, err) =>
+ val stderr = wsk.cli(cmd, expectedExitCode = MISUSE_EXIT).stderr
+ stderr should include(err)
+ stderr should include("Run 'wsk --help' for usage.")
+ }
+ }
+
+ it should "reject commands that are executed with not enough param or annot arguments" in {
val invalidParamMsg = "Arguments for '-p' must be a key/value pair"
val invalidAnnotMsg = "Arguments for '-a' must be a key/value pair"
+ val invalidParamFileMsg = "An argument must be provided for '-P'"
+ val invalidAnnotFileMsg = "An argument must be provided for '-A'"
val invalidArgs = Seq(
(Seq("action", "create", "actionName", "-p"), invalidParamMsg),
(Seq("action", "create", "actionName", "-p", "key"), invalidParamMsg),
+ (Seq("action", "create", "actionName", "-P"), invalidParamFileMsg),
(Seq("action", "update", "actionName", "-p"), invalidParamMsg),
(Seq("action", "update", "actionName", "-p", "key"), invalidParamMsg),
+ (Seq("action", "update", "actionName", "-P"), invalidParamFileMsg),
(Seq("action", "invoke", "actionName", "-p"), invalidParamMsg),
(Seq("action", "invoke", "actionName", "-p", "key"), invalidParamMsg),
+ (Seq("action", "invoke", "actionName", "-P"), invalidParamFileMsg),
(Seq("action", "create", "actionName", "-a"), invalidAnnotMsg),
(Seq("action", "create", "actionName", "-a", "key"), invalidAnnotMsg),
+ (Seq("action", "create", "actionName", "-A"), invalidAnnotFileMsg),
(Seq("action", "update", "actionName", "-a"), invalidAnnotMsg),
(Seq("action", "update", "actionName", "-a", "key"), invalidAnnotMsg),
+ (Seq("action", "update", "actionName", "-A"), invalidAnnotFileMsg),
(Seq("action", "invoke", "actionName", "-a"), invalidAnnotMsg),
(Seq("action", "invoke", "actionName", "-a", "key"), invalidAnnotMsg),
+ (Seq("action", "invoke", "actionName", "-A"), invalidAnnotFileMsg),
(Seq("package", "create", "packageName", "-p"), invalidParamMsg),
(Seq("package", "create", "packageName", "-p", "key"), invalidParamMsg),
+ (Seq("package", "create", "packageName", "-P"), invalidParamFileMsg),
(Seq("package", "update", "packageName", "-p"), invalidParamMsg),
(Seq("package", "update", "packageName", "-p", "key"), invalidParamMsg),
+ (Seq("package", "update", "packageName", "-P"), invalidParamFileMsg),
(Seq("package", "bind", "packageName", "boundPackageName", "-p"), invalidParamMsg),
(Seq("package", "bind", "packageName", "boundPackageName", "-p", "key"), invalidParamMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-P"), invalidParamFileMsg),
(Seq("package", "create", "packageName", "-a"), invalidAnnotMsg),
(Seq("package", "create", "packageName", "-a", "key"), invalidAnnotMsg),
+ (Seq("package", "create", "packageName", "-A"), invalidAnnotFileMsg),
(Seq("package", "update", "packageName", "-a"), invalidAnnotMsg),
(Seq("package", "update", "packageName", "-a", "key"), invalidAnnotMsg),
+ (Seq("package", "update", "packageName", "-A"), invalidAnnotFileMsg),
(Seq("package", "bind", "packageName", "boundPackageName", "-a"), invalidAnnotMsg),
(Seq("package", "bind", "packageName", "boundPackageName", "-a", "key"), invalidAnnotMsg),
+ (Seq("package", "bind", "packageName", "boundPackageName", "-A"), invalidAnnotFileMsg),
(Seq("trigger", "create", "triggerName", "-p"), invalidParamMsg),
(Seq("trigger", "create", "triggerName", "-p", "key"), invalidParamMsg),
+ (Seq("trigger", "create", "triggerName", "-P"), invalidParamFileMsg),
(Seq("trigger", "update", "triggerName", "-p"), invalidParamMsg),
(Seq("trigger", "update", "triggerName", "-p", "key"), invalidParamMsg),
+ (Seq("trigger", "update", "triggerName", "-P"), invalidParamFileMsg),
(Seq("trigger", "fire", "triggerName", "-p"), invalidParamMsg),
(Seq("trigger", "fire", "triggerName", "-p", "key"), invalidParamMsg),
+ (Seq("trigger", "fire", "triggerName", "-P"), invalidParamFileMsg),
(Seq("trigger", "create", "triggerName", "-a"), invalidAnnotMsg),
(Seq("trigger", "create", "triggerName", "-a", "key"), invalidAnnotMsg),
+ (Seq("trigger", "create", "triggerName", "-A"), invalidAnnotFileMsg),
(Seq("trigger", "update", "triggerName", "-a"), invalidAnnotMsg),
(Seq("trigger", "update", "triggerName", "-a", "key"), invalidAnnotMsg),
+ (Seq("trigger", "update", "triggerName", "-A"), invalidAnnotFileMsg),
(Seq("trigger", "fire", "triggerName", "-a"), invalidAnnotMsg),
- (Seq("trigger", "fire", "triggerName", "-a", "key"), invalidAnnotMsg))
+ (Seq("trigger", "fire", "triggerName", "-a", "key"), invalidAnnotMsg),
+ (Seq("trigger", "fire", "triggerName", "-A"), invalidAnnotFileMsg)
+ )
invalidArgs foreach {
case (cmd, err) =>