Add ActionProxyContainer tests (#47)
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionProxyContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/ActionProxyContainerTests.scala
new file mode 100644
index 0000000..20a9ee5
--- /dev/null
+++ b/tests/src/test/scala/runtime/actionContainers/ActionProxyContainerTests.scala
@@ -0,0 +1,248 @@
+/*
+ * 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 runtime.actionContainers
+
+import java.io.File
+import java.util.Base64
+
+import org.apache.commons.io.FileUtils
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import actionContainers.{ActionContainer, BasicActionRunnerTests}
+import actionContainers.ActionContainer.withContainer
+import common.TestUtils
+import common.WskActorSystem
+import spray.json._
+
+@RunWith(classOf[JUnitRunner])
+class ActionProxyContainerTests extends BasicActionRunnerTests with WskActorSystem {
+
+ override def withActionContainer(env: Map[String, String] = Map.empty)(code: ActionContainer => Unit) = {
+ withContainer("dockerskeleton", env)(code)
+ }
+
+ val codeNotReturningJson = """
+ |#!/bin/sh
+ |echo not a json object
+ """.stripMargin.trim
+
+ /** Standard code samples, should print 'hello' to stdout and echo the input args. */
+ val stdCodeSamples = {
+ val bash = """
+ |#!/bin/bash
+ |echo 'hello stdout'
+ |echo 'hello stderr' 1>&2
+ |if [[ -z $1 || $1 == '{}' ]]; then
+ | echo '{ "msg": "Hello from bash script!" }'
+ |else
+ | echo $1 # echo the arguments back as the result
+ |fi
+ """.stripMargin.trim
+
+ val python = """
+ |#!/usr/bin/env python
+ |from __future__ import print_function
+ |import sys
+ |print('hello stdout')
+ |print('hello stderr', file=sys.stderr)
+ |print(sys.argv[1])
+ """.stripMargin.trim
+
+ val perl = """
+ |#!/usr/bin/env perl
+ |print STDOUT "hello stdout\n";
+ |print STDERR "hello stderr\n";
+ |print $ARGV[0];
+ """.stripMargin.trim
+
+ Seq(("bash", bash), ("python", python), ("perl", perl))
+ }
+
+ val stdUnicodeSamples = {
+ // python 3 in base image
+ val python = """
+ |#!/usr/bin/env python
+ |import json, sys
+ |j = json.loads(sys.argv[1])
+ |sep = j["delimiter"]
+ |s = sep + " ☃ " + sep
+ |print(s)
+ |print(json.dumps({"winter": s}))
+ """.stripMargin.trim
+
+ Seq(("python", python))
+ }
+
+ /** Standard code samples, should print 'hello' to stdout and echo the input args. */
+ val stdEnvSamples = {
+ val bash = """
+ |#!/bin/bash
+ |echo "{ \
+ |\"api_host\": \"$__OW_API_HOST\", \"api_key\": \"$__OW_API_KEY\", \
+ |\"namespace\": \"$__OW_NAMESPACE\", \"action_name\": \"$__OW_ACTION_NAME\", \
+ |\"activation_id\": \"$__OW_ACTIVATION_ID\", \"deadline\": \"$__OW_DEADLINE\" }"
+ """.stripMargin.trim
+
+ val python =
+ """
+ |#!/usr/bin/env python
+ |import os
+ |
+ |print('{ "api_host": "%s", "api_key": "%s", "namespace": "%s", "action_name" : "%s", "activation_id": "%s", "deadline": "%s" }' % (
+ | os.environ['__OW_API_HOST'], os.environ['__OW_API_KEY'],
+ | os.environ['__OW_NAMESPACE'], os.environ['__OW_ACTION_NAME'],
+ | os.environ['__OW_ACTIVATION_ID'], os.environ['__OW_DEADLINE']))
+ """.stripMargin.trim
+
+ val perl =
+ """
+ |#!/usr/bin/env perl
+ |$a = $ENV{'__OW_API_HOST'};
+ |$b = $ENV{'__OW_API_KEY'};
+ |$c = $ENV{'__OW_NAMESPACE'};
+ |$d = $ENV{'__OW_ACTION_NAME'};
+ |$e = $ENV{'__OW_ACTIVATION_ID'};
+ |$f = $ENV{'__OW_DEADLINE'};
+ |print "{ \"api_host\": \"$a\", \"api_key\": \"$b\", \"namespace\": \"$c\", \"action_name\": \"$d\", \"activation_id\": \"$e\", \"deadline\": \"$f\" }";
+ """.stripMargin.trim
+
+ Seq(("bash", bash), ("python", python), ("perl", perl))
+ }
+
+ /** Large param samples, echo the input args with input larger than 128K and using STDIN */
+ val stdLargeInputSamples = {
+ val bash = """
+ |#!/bin/bash
+ | read inputstring
+ | echo $inputstring
+ """.stripMargin.trim
+
+ val python = """
+ |#!/usr/bin/env python
+ |import sys, json
+ |params = sys.stdin.readline()
+ |j = json.loads(params)
+ |print(json.dumps(j))
+ """.stripMargin.trim
+
+ val perl = """
+ |#!/usr/bin/env perl
+ |$params=<STDIN>;
+ |print $params;
+ """.stripMargin.trim
+
+ Seq(("bash", bash), ("python", python), ("perl", perl))
+ }
+
+ behavior of "openwhisk/dockerskeleton"
+
+ it should "run sample without init" in {
+ val (out, err) = withActionContainer() { c =>
+ val (runCode, out) = c.run(JsObject())
+ runCode should be(200)
+ out should be(Some(JsObject("error" -> JsString("This is a stub action. Replace it with custom logic."))))
+ }
+
+ checkStreams(out, err, {
+ case (o, _) => o should include("This is a stub action")
+ })
+ }
+
+ it should "run sample with 'null' init" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, _) = c.init(initPayload(null))
+ initCode should be(200)
+
+ val (runCode, out) = c.run(JsObject())
+ runCode should be(200)
+ out should be(Some(JsObject("error" -> JsString("This is a stub action. Replace it with custom logic."))))
+ }
+
+ checkStreams(out, err, {
+ case (o, _) => o should include("This is a stub action")
+ })
+ }
+
+ it should "run sample with init that does nothing" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, _) = c.init(JsObject())
+ initCode should be(200)
+ val (runCode, out) = c.run(JsObject())
+ runCode should be(200)
+ out should be(Some(JsObject("error" -> JsString("This is a stub action. Replace it with custom logic."))))
+ }
+
+ checkStreams(out, err, {
+ case (o, _) => o should include("This is a stub action")
+ })
+ }
+
+ it should "respond with 404 for bad run argument" in {
+ val (out, err) = withActionContainer() { c =>
+ val (runCode, out) = c.run(runPayload(JsString("A")))
+ runCode should be(404)
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ o shouldBe empty
+ e shouldBe empty
+ })
+ }
+
+ it should "fail to run a bad script" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, _) = c.init(initPayload(""))
+ initCode should be(200)
+ val (runCode, out) = c.run(JsNull)
+ runCode should be(502)
+ out should be(Some(JsObject("error" -> JsString("The action did not return a dictionary."))))
+ }
+
+ checkStreams(out, err, {
+ case (o, _) => o should include("error")
+ })
+ }
+
+ it should "extract and run a compatible zip exec" in {
+ val zip = FileUtils.readFileToByteArray(new File(TestUtils.getTestActionFilename("blackbox.zip")))
+ val contents = Base64.getEncoder.encodeToString(zip)
+
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, err) =
+ c.init(JsObject("value" -> JsObject("code" -> JsString(contents), "binary" -> JsBoolean(true))))
+ initCode should be(200)
+ val (runCode, out) = c.run(JsObject())
+ runCode should be(200)
+ out.get should be(JsObject("msg" -> JsString("hello zip")))
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ o shouldBe "This is an example zip used with the docker skeleton action."
+ e shouldBe empty
+ })
+ }
+
+ testNotReturningJson(codeNotReturningJson, checkResultInLogs = true)
+ testEcho(stdCodeSamples)
+ testUnicode(stdUnicodeSamples)
+ testEnv(stdEnvSamples)
+ testLargeInput(stdLargeInputSamples)
+}
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index 40d6d7a..0b3f18f 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -42,7 +42,7 @@
docker pull openwhisk/invoker
docker tag openwhisk/invoker ${IMAGE_PREFIX}/invoker
docker pull openwhisk/nodejs6action
-docker tag openwhisk/nodejs6action ${IMAGE_PREFIX}/nodejs6action
+docker tag openwhisk/nodejs6action nodejs6action
TERM=dumb ./gradlew install