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 <s...@us.ibm.com>
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")
+    }
+  }
+
+}

Reply via email to