This is an automated email from the ASF dual-hosted git repository.
houshengbo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push:
new 2ec03a3 Fix the test report issue, so all the test result is posted
(#4404)
2ec03a3 is described below
commit 2ec03a3557c112d9d12b20870ab39b7bc8053eea
Author: Vincent <[email protected]>
AuthorDate: Thu Mar 28 21:15:54 2019 -0400
Fix the test report issue, so all the test result is posted (#4404)
---
Jenkinsfile | 146 ++++-----
tests/build.gradle | 17 +-
.../scala/invokerShoot/ShootInvokerTests.scala | 340 +++++++++++++++++++++
3 files changed, 432 insertions(+), 71 deletions(-)
diff --git a/Jenkinsfile b/Jenkinsfile
index 15ae524..6cf8723 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -25,92 +25,100 @@ timeout(time: 12, unit: 'HOURS') {
node("openwhisk") {
def hostName = sh(returnStdout: true, script: 'hostname').trim()
def domainName = hostName+".apache.org"
+ def home = sh(returnStdout: true, script: 'echo $HOME').trim()
+ def jobName = sh(returnStdout: true, script: 'echo $JOB_NAME').trim()
+ def jobSpace = "${home}/jenkins-slave/workspace/${jobName}"
+
lock("${hostName}") {
- try {
- deleteDir()
- stage('Checkout') {
- checkout scm
- }
-
- stage('Build') {
- // Set up a private docker registry service, accessed by
all the OpenWhisk VMs.
- try {
- sh "docker container stop registry && docker container
rm -v registry"
- } catch (exp) {
- println("Unable to stop and remove the container
registry.")
+ sh "mkdir -p ${jobSpace}"
+ dir("${jobSpace}") {
+ try {
+ deleteDir()
+ stage('Checkout') {
+ checkout scm
}
- sh "docker run -d --restart=always --name registry -v
\"$HOME\"/certs:/certs \
- -e REGISTRY_HTTP_ADDR=0.0.0.0:${port} -e
REGISTRY_HTTP_TLS_CERTIFICATE=/certs/${cert} \
- -e REGISTRY_HTTP_TLS_KEY=/certs/${key} -p
${port}:${port} registry:2"
- // Build the controller and invoker images.
- sh "./gradlew distDocker
-PdockerRegistry=${domainName}:${port}"
- }
+ stage('Build') {
+ // Set up a private docker registry service, accessed
by all the OpenWhisk VMs.
+ try {
+ sh "docker container stop registry && docker
container rm -v registry"
+ } catch (exp) {
+ println("Unable to stop and remove the container
registry.")
+ }
- stage('Deploy') {
- dir("ansible") {
- // Copy the jenkins ansible configuration under the
directory ansible. This can make sure the SSH is used to
- // access the VMs of invokers by the VM of the
controller.
- sh '[ -f "environments/jenkins/ansible_jenkins.cfg" ]
&& cp environments/jenkins/ansible_jenkins.cfg ansible.cfg'
+ sh "docker run -d --restart=always --name registry -v
\"$HOME\"/certs:/certs \
+ -e REGISTRY_HTTP_ADDR=0.0.0.0:${port} -e
REGISTRY_HTTP_TLS_CERTIFICATE=/certs/${cert} \
+ -e REGISTRY_HTTP_TLS_KEY=/certs/${key} -p
${port}:${port} registry:2"
+ // Build the controller and invoker images.
+ sh "./gradlew distDocker
-PdockerRegistry=${domainName}:${port}"
}
- dir("ansible/environments/jenkins") {
- sh "cp ${hostName}.j2.ini hosts.j2.ini"
- }
+ stage('Deploy') {
+ dir("ansible") {
+ // Copy the jenkins ansible configuration under
the directory ansible. This can make sure the SSH is used to
+ // access the VMs of invokers by the VM of the
controller.
+ sh '[ -f
"environments/jenkins/ansible_jenkins.cfg" ] && cp
environments/jenkins/ansible_jenkins.cfg ansible.cfg'
+ }
+
+ dir("ansible/environments/jenkins") {
+ sh "cp ${hostName}.j2.ini hosts.j2.ini"
+ }
+
+ dir("ansible/environments/jenkins/group_vars") {
+ sh "cp ${hostName} all"
+ }
- dir("ansible/environments/jenkins/group_vars") {
- sh "cp ${hostName} all"
+ dir("ansible") {
+ sh 'ansible-playbook -i environments/jenkins
setup.yml'
+ sh 'ansible-playbook -i environments/jenkins
openwhisk.yml -e mode=clean'
+ sh 'ansible-playbook -i environments/jenkins
apigateway.yml -e mode=clean'
+ sh 'ansible-playbook -i environments/jenkins
couchdb.yml -e mode=clean'
+ sh 'ansible-playbook -i environments/jenkins
couchdb.yml'
+ sh 'ansible-playbook -i environments/jenkins
initdb.yml'
+ sh 'ansible-playbook -i environments/jenkins
wipe.yml'
+ sh 'ansible-playbook -i environments/jenkins
apigateway.yml'
+ sh 'ansible-playbook -i environments/jenkins
openwhisk.yml'
+ sh 'ansible-playbook -i environments/jenkins
properties.yml'
+ sh 'ansible-playbook -i environments/jenkins
routemgmt.yml'
+ sh 'ansible-playbook -i environments/jenkins
postdeploy.yml'
+ }
}
- dir("ansible") {
- sh 'ansible-playbook -i environments/jenkins setup.yml'
- sh 'ansible-playbook -i environments/jenkins
openwhisk.yml -e mode=clean'
- sh 'ansible-playbook -i environments/jenkins
apigateway.yml -e mode=clean'
- sh 'ansible-playbook -i environments/jenkins
couchdb.yml -e mode=clean'
- sh 'ansible-playbook -i environments/jenkins
couchdb.yml'
- sh 'ansible-playbook -i environments/jenkins
initdb.yml'
- sh 'ansible-playbook -i environments/jenkins wipe.yml'
- sh 'ansible-playbook -i environments/jenkins
apigateway.yml'
- sh 'ansible-playbook -i environments/jenkins
openwhisk.yml'
- sh 'ansible-playbook -i environments/jenkins
properties.yml'
- sh 'ansible-playbook -i environments/jenkins
routemgmt.yml'
- sh 'ansible-playbook -i environments/jenkins
postdeploy.yml'
+ try {
+ stage('Test') {
+ sh './gradlew :tests:test
-DtestResultsDirName=test-openwhisk'
+ }
+ } catch (exp) {
+ println("Exception:" + exp)
}
- }
- try {
- stage('Test') {
- sh './gradlew :tests:test'
+ try {
+ stage('Shoot one invoker test') {
+ def folder =
"ansible/environments/jenkins/group_vars"
+ def invoker1_node = sh(returnStdout: true,
+ script: "grep invoker1_machine
${folder}/${hostName} | cut -d: -f2").trim()
+ sh "ssh -i ${home}/secret/openwhisk_key
openwhisk@${invoker1_node} 'docker stop invoker1'"
+ sleep time: 1, unit: 'MINUTES'
+ sh './gradlew :tests:testShootInvoker
-DtestResultsDirName=test-shoot-invoker'
+ sh "ssh -i ${home}/secret/openwhisk_key
openwhisk@${invoker1_node} 'docker start invoker1'"
+ }
+ } catch (exp) {
+ println("Exception:" + exp)
}
- } catch (exp) {
- println("Exception:" + exp)
- }
- try {
- stage('Shoot one invoker test') {
- def folder = "ansible/environments/jenkins/group_vars"
- def invoker1_node = sh(returnStdout: true,
- script: "grep invoker1_machine
${folder}/${hostName} | cut -d: -f2").trim()
- sh "ssh -i ${home}/secret/openwhisk_key
openwhisk@${invoker1_node} 'docker stop invoker1'"
- sleep time: 1, unit: 'MINUTES'
- sh './gradlew :tests:test
-Dtest.single=*WskActionTests*'
- sh "ssh -i ${home}/secret/openwhisk_key
openwhisk@${invoker1_node} 'docker start invoker1'"
+ stage('Clean up') {
+ dir("ansible") {
+ sh 'ansible-playbook -i environments/jenkins
openwhisk.yml -e mode=clean'
+ sh 'ansible-playbook -i environments/jenkins
apigateway.yml -e mode=clean'
+ sh 'ansible-playbook -i environments/jenkins
couchdb.yml -e mode=clean'
+ }
}
+
} catch (exp) {
println("Exception:" + exp)
+ } finally {
+ step([$class: 'JUnitResultArchiver', testResults:
'**/test*/**/TEST-*.xml'])
}
-
- stage('Clean up') {
- dir("ansible") {
- sh 'ansible-playbook -i environments/jenkins
openwhisk.yml -e mode=clean'
- sh 'ansible-playbook -i environments/jenkins
apigateway.yml -e mode=clean'
- sh 'ansible-playbook -i environments/jenkins
couchdb.yml -e mode=clean'
- }
- }
- } catch (exp) {
- println("Exception:" + exp)
- } finally {
- step([$class: 'JUnitResultArchiver', testResults:
'**/test-results/**/TEST-*.xml'])
}
}
}
diff --git a/tests/build.gradle b/tests/build.gradle
index d578c71..2b93585 100644
--- a/tests/build.gradle
+++ b/tests/build.gradle
@@ -49,6 +49,7 @@ tasks.withType(Test) {
def leanExcludes = [
'**/MaxActionDurationTests*',
+ 'invokerShoot/**'
]
def systemIncludes = [
@@ -78,12 +79,14 @@ ext.testSets = [
"**/*CacheConcurrencyTests*",
"**/*ControllerApiTests*",
"org/apache/openwhisk/testEntities/**",
+ 'invokerShoot/**'
]
],
"REQUIRE_SYSTEM" : [
"includes" : systemIncludes,
"excludes": [
- "system/basic/WskMultiRuntimeTests*"
+ "system/basic/WskMultiRuntimeTests*",
+ 'invokerShoot/**'
]
],
"REQUIRE_MULTI_RUNTIME" : [
@@ -107,7 +110,8 @@ ext.testSets = [
// Tests suits below require Kafka so they are excluded for Lean
System tests
"excludes" : [
"**/*KafkaConnectorTests*",
- "system/basic/WskMultiRuntimeTests*"
+ "system/basic/WskMultiRuntimeTests*",
+ "invokerShoot/**"
]
]
]
@@ -135,6 +139,14 @@ def logTestSetInfo(){
println "Using testSet $testSetName -
${prettyPrint(toJson(testSets[testSetName]))}"
}
+test {
+ exclude 'invokerShoot/**'
+}
+
+task testShootInvoker(type: Test) {
+ include 'invokerShoot/**'
+}
+
task testLean(type: Test) {
doFirst {
logTestSetInfo()
@@ -161,6 +173,7 @@ task testUnit(type: Test) {
"**/*RemoveLogsTests*",
"**/*ReplicatorTest*",
"**/*CouchDBArtifactStoreTests*",
+ "invokerShoot/**"
]
exclude couchDbExcludes
diff --git a/tests/src/test/scala/invokerShoot/ShootInvokerTests.scala
b/tests/src/test/scala/invokerShoot/ShootInvokerTests.scala
new file mode 100644
index 0000000..e40bccc
--- /dev/null
+++ b/tests/src/test/scala/invokerShoot/ShootInvokerTests.scala
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package invokerShoot
+
+import java.io.File
+import java.nio.charset.StandardCharsets
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+import common._
+import common.rest.WskRestOperations
+import org.apache.openwhisk.core.entity.WhiskAction
+import org.apache.commons.io.FileUtils
+import spray.json._
+import spray.json.DefaultJsonProtocol._
+
+@RunWith(classOf[JUnitRunner])
+class ShootInvokerTests extends TestHelpers with WskTestHelpers with JsHelpers
with WskActorSystem {
+
+ implicit val wskprops = WskProps()
+ // wsk must have type WskOperations so that tests using CLI (class Wsk)
+ // instead of REST (WskRestOperations) still work.
+ val wsk: WskOperations = new WskRestOperations
+
+ val testString = "this is a test"
+ val testResult = JsObject("count" -> testString.split(" ").length.toJson)
+ val guestNamespace = wskprops.namespace
+
+ behavior of "Whisk actions"
+
+ it should "create an action with an empty file" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "empty"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, Some(TestUtils.getTestActionFilename("empty.js")))
+ }
+ }
+
+ it should "invoke an action returning a promise" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "hello promise"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
Some(TestUtils.getTestActionFilename("helloPromise.js")))
+ }
+
+ val run = wsk.action.invoke(name)
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "success"
+ activation.response.result shouldBe Some(JsObject("done" -> true.toJson))
+ activation.logs.get.mkString(" ") shouldBe empty
+ }
+ }
+
+ it should "invoke an action with a space in the name" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "hello Async"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
Some(TestUtils.getTestActionFilename("helloAsync.js")))
+ }
+
+ val run = wsk.action.invoke(name, Map("payload" -> testString.toJson))
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "success"
+ activation.response.result shouldBe Some(testResult)
+ activation.logs.get.mkString(" ") should include(testString)
+ }
+ }
+
+ it should "invoke an action that throws an uncaught exception and returns
correct status code" in withAssetCleaner(
+ wskprops) { (wp, assetHelper) =>
+ val name = "throwExceptionAction"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
Some(TestUtils.getTestActionFilename("runexception.js")))
+ }
+
+ withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+ val response = activation.response
+ activation.response.status shouldBe "action developer error"
+ activation.response.result shouldBe Some(
+ JsObject("error" -> "An error has occurred: Extraordinary
exception".toJson))
+ }
+ }
+
+ it should "pass parameters bound on creation-time to the action" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "printParams"
+ val params = Map("param1" -> "test1", "param2" -> "test2")
+
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(
+ name,
+ Some(TestUtils.getTestActionFilename("printParams.js")),
+ parameters = params.mapValues(_.toJson))
+ }
+
+ val invokeParams = Map("payload" -> testString)
+ val run = wsk.action.invoke(name, invokeParams.mapValues(_.toJson))
+ withActivation(wsk.activation, run) { activation =>
+ val logs = activation.logs.get.mkString(" ")
+
+ (params ++ invokeParams).foreach {
+ case (key, value) =>
+ logs should include(s"params.$key: $value")
+ }
+ }
+ }
+
+ it should "copy an action and invoke it successfully" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "copied"
+ val packageName = "samples"
+ val actionName = "wordcount"
+ val fullQualifiedName = s"/$guestNamespace/$packageName/$actionName"
+
+ assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+ pkg.create(packageName, shared = Some(true))
+ }
+
+ assetHelper.withCleaner(wsk.action, fullQualifiedName) {
+ val file = Some(TestUtils.getTestActionFilename("wc.js"))
+ (action, _) =>
+ action.create(fullQualifiedName, file)
+ }
+
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, Some(fullQualifiedName), Some("copy"))
+ }
+
+ val run = wsk.action.invoke(name, Map("payload" -> testString.toJson))
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "success"
+ activation.response.result shouldBe Some(testResult)
+ activation.logs.get.mkString(" ") should include(testString)
+ }
+ }
+
+ it should "copy an action and ensure exec, parameters, and annotations
copied" in withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ val origActionName = "origAction"
+ val copiedActionName = "copiedAction"
+ val params = Map("a" -> "A".toJson)
+ val annots = Map("b" -> "B".toJson)
+
+ assetHelper.withCleaner(wsk.action, origActionName) {
+ val file = Some(TestUtils.getTestActionFilename("wc.js"))
+ (action, _) =>
+ action.create(origActionName, file, parameters = params, annotations
= annots)
+ }
+
+ assetHelper.withCleaner(wsk.action, copiedActionName) { (action, _) =>
+ action.create(copiedActionName, Some(origActionName), Some("copy"))
+ }
+
+ val copiedAction =
wsk.parseJsonString(wsk.action.get(copiedActionName).stdout)
+ val origAction =
wsk.parseJsonString(wsk.action.get(copiedActionName).stdout)
+
+ copiedAction.fields("annotations") shouldBe
origAction.fields("annotations")
+ copiedAction.fields("parameters") shouldBe
origAction.fields("parameters")
+ copiedAction.fields("exec") shouldBe origAction.fields("exec")
+ copiedAction.fields("version") shouldBe JsString("0.0.1")
+ }
+
+ it should "add new parameters and annotations while copying an action" in
withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ val origName = "origAction"
+ val copiedName = "copiedAction"
+ val origParams = Map("origParam1" -> "origParamValue1".toJson,
"origParam2" -> 999.toJson)
+ val copiedParams = Map("copiedParam1" -> "copiedParamValue1".toJson,
"copiedParam2" -> 123.toJson)
+ val origAnnots = Map("origAnnot1" -> "origAnnotValue1".toJson,
"origAnnot2" -> true.toJson)
+ val copiedAnnots = Map("copiedAnnot1" -> "copiedAnnotValue1".toJson,
"copiedAnnot2" -> false.toJson)
+ val resParams = Seq(
+ JsObject("key" -> JsString("copiedParam1"), "value" ->
JsString("copiedParamValue1")),
+ JsObject("key" -> JsString("copiedParam2"), "value" -> JsNumber(123)),
+ JsObject("key" -> JsString("origParam1"), "value" ->
JsString("origParamValue1")),
+ JsObject("key" -> JsString("origParam2"), "value" -> JsNumber(999)))
+ val resAnnots = Seq(
+ JsObject("key" -> JsString("origAnnot1"), "value" ->
JsString("origAnnotValue1")),
+ JsObject("key" -> JsString("copiedAnnot2"), "value" ->
JsBoolean(false)),
+ JsObject("key" -> JsString("copiedAnnot1"), "value" ->
JsString("copiedAnnotValue1")),
+ JsObject("key" -> JsString("origAnnot2"), "value" -> JsBoolean(true)),
+ JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")),
+ JsObject("key" -> WhiskAction.provideApiKeyAnnotationName.toJson,
"value" -> JsBoolean(false)))
+
+ assetHelper.withCleaner(wsk.action, origName) {
+ val file = Some(TestUtils.getTestActionFilename("echo.js"))
+ (action, _) =>
+ action.create(origName, file, parameters = origParams, annotations =
origAnnots)
+ }
+
+ assetHelper.withCleaner(wsk.action, copiedName) { (action, _) =>
+ println("created copied ")
+ action.create(copiedName, Some(origName), Some("copy"), parameters =
copiedParams, annotations = copiedAnnots)
+ }
+
+ val copiedAction = wsk.parseJsonString(wsk.action.get(copiedName).stdout)
+
+ // CLI does not guarantee order of annotations and parameters so do a
diff to compare the values
+ copiedAction.fields("parameters").convertTo[Seq[JsObject]] diff
resParams shouldBe List.empty
+ copiedAction.fields("annotations").convertTo[Seq[JsObject]] diff
resAnnots shouldBe List.empty
+ }
+
+ it should "recreate and invoke a new action with different code" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "recreatedAction"
+ assetHelper.withCleaner(wsk.action, name, false) { (action, _) =>
+ action.create(name, Some(TestUtils.getTestActionFilename("wc.js")))
+ }
+
+ val run1 = wsk.action.invoke(name, Map("payload" -> testString.toJson))
+ withActivation(wsk.activation, run1) { activation =>
+ activation.response.status shouldBe "success"
+ activation.logs.get.mkString(" ") should include(s"The message
'$testString' has")
+ }
+
+ wsk.action.delete(name)
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, Some(TestUtils.getTestActionFilename("hello.js")))
+ }
+
+ val run2 = wsk.action.invoke(name, Map("payload" -> testString.toJson))
+ withActivation(wsk.activation, run2) { activation =>
+ activation.response.status shouldBe "success"
+ activation.logs.get.mkString(" ") should include(s"hello, $testString")
+ }
+ }
+
+ it should "fail to invoke an action with an empty file" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "empty"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, Some(TestUtils.getTestActionFilename("empty.js")))
+ }
+ val run = wsk.action.invoke(name)
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "action developer error"
+ activation.response.result shouldBe Some(JsObject("error" -> "Missing
main/no code to execute.".toJson))
+ }
+ }
+
+ it should "blocking invoke of nested blocking actions" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "nestedBlockingAction"
+ val child = "wc"
+
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(
+ name,
+ Some(TestUtils.getTestActionFilename("wcbin.js")),
+ annotations = Map(WhiskAction.provideApiKeyAnnotationName ->
JsBoolean(true)))
+ }
+ assetHelper.withCleaner(wsk.action, child) { (action, _) =>
+ action.create(child, Some(TestUtils.getTestActionFilename("wc.js")))
+ }
+
+ val run = wsk.action.invoke(name, Map("payload" -> testString.toJson),
blocking = true)
+ val activation =
wsk.parseJsonString(run.stdout).convertTo[ActivationResult]
+
+ withClue(s"check failed for activation: $activation") {
+ val wordCount = testString.split(" ").length
+ activation.response.result.get shouldBe JsObject("binaryCount" ->
s"${wordCount.toBinaryString} (base 2)".toJson)
+ }
+ }
+
+ it should "blocking invoke an asynchronous action" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "helloAsync"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name,
Some(TestUtils.getTestActionFilename("helloAsync.js")))
+ }
+
+ val run = wsk.action.invoke(name, Map("payload" -> testString.toJson),
blocking = true)
+ val activation =
wsk.parseJsonString(run.stdout).convertTo[ActivationResult]
+
+ withClue(s"check failed for activation: $activation") {
+ activation.response.status shouldBe "success"
+ activation.response.result shouldBe Some(testResult)
+ activation.logs shouldBe Some(List.empty)
+ }
+ }
+
+ it should "not be able to use 'ping' in an action" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "ping"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, Some(TestUtils.getTestActionFilename("ping.js")))
+ }
+
+ val run = wsk.action.invoke(name, Map("payload" -> "google.com".toJson))
+ withActivation(wsk.activation, run) { activation =>
+ val result = activation.response.result.get
+ result.getFields("stdout", "code") match {
+ case Seq(JsString(stdout), JsNumber(code)) =>
+ stdout should not include "bytes from"
+ code.intValue() should not be 0
+ case _ => fail(s"fields 'stdout' or 'code' where not of the expected
format, was $result")
+ }
+ }
+ }
+
+ it should "support UTF-8 as input and output format" in
withAssetCleaner(wskprops) { (wp, assetHelper) =>
+ val name = "utf8Test"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ action.create(name, Some(TestUtils.getTestActionFilename("hello.js")))
+ }
+
+ val utf8 = "«ταБЬℓσö»: 1<2 & 4+1>³, now 20%€§$ off!"
+ val run = wsk.action.invoke(name, Map("payload" -> utf8.toJson))
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "success"
+ activation.logs.get.mkString(" ") should include(s"hello, $utf8")
+ }
+ }
+
+ it should "invoke action with large code" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
+ val name = "big-hello"
+ assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+ val filePath = TestUtils.getTestActionFilename("hello.js")
+ val code = FileUtils.readFileToString(new File(filePath),
StandardCharsets.UTF_8)
+ val largeCode = code + " " * (WhiskProperties.getMaxActionSizeMB *
FileUtils.ONE_MB).toInt
+ val tmpFile = File.createTempFile("whisk", ".js")
+ FileUtils.write(tmpFile, largeCode, StandardCharsets.UTF_8)
+ val result = action.create(name, Some(tmpFile.getAbsolutePath))
+ tmpFile.delete()
+ result
+ }
+
+ val hello = "hello"
+ val run = wsk.action.invoke(name, Map("payload" -> hello.toJson))
+ withActivation(wsk.activation, run) { activation =>
+ activation.response.status shouldBe "success"
+ activation.logs.get.mkString(" ") should include(s"hello, $hello")
+ }
+ }
+
+}