You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2018/08/23 22:36:45 UTC

[GitHub] rabbah closed pull request #45: Unit tests

rabbah closed pull request #45: Unit tests
URL: https://github.com/apache/incubator-openwhisk-runtime-go/pull/45
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/.gitignore b/.gitignore
index 16ffbc9..793f57e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
 .gradle/
 .gogradle/
 *.log
+tests/build/
 
 # Dependencies
 vendor/
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index d7cc33f..abd704b 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -5,4 +5,4 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
diff --git a/settings.gradle b/settings.gradle
index 4a24586..1892607 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -15,6 +15,8 @@
  * limitations under the License.
  */
 
+include 'tests'
+
 include 'actionProxyLoop'
 include 'golang1.10'
 
diff --git a/tests/build.gradle b/tests/build.gradle
new file mode 100644
index 0000000..1ae5a4b
--- /dev/null
+++ b/tests/build.gradle
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+apply plugin: 'scala'
+apply plugin: 'eclipse'
+compileTestScala.options.encoding = 'UTF-8'
+
+repositories {
+    mavenCentral()
+    mavenLocal()
+}
+
+tasks.withType(Test) {
+    testLogging {
+        events "passed", "skipped", "failed"
+        showStandardStreams = true
+        exceptionFormat = 'full'
+    }
+    outputs.upToDateWhen { false } // force tests to run every time
+}
+
+dependencies {
+    compile "org.scala-lang:scala-library:${gradle.scala.version}"
+    compile "org.apache.openwhisk:openwhisk-tests:${gradle.openwhisk.version}:tests"
+    compile "org.apache.openwhisk:openwhisk-tests:${gradle.openwhisk.version}:test-sources"
+}
+
+tasks.withType(ScalaCompile) {
+    scalaCompileOptions.additionalParameters = gradle.scala.compileFlags
+}
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionLoopContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/ActionLoopContainerTests.scala
new file mode 100644
index 0000000..ef11078
--- /dev/null
+++ b/tests/src/test/scala/runtime/actionContainers/ActionLoopContainerTests.scala
@@ -0,0 +1,92 @@
+/*
+ * 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.util.concurrent.TimeoutException
+import actionContainers.{ActionContainer, ActionProxyContainerTestUtils}
+import actionContainers.ActionContainer.withContainer
+import common.WskActorSystem
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+//import spray.json.JsNumber
+import spray.json.{JsObject, JsString}
+//import spray.json.JsBoolean
+
+@RunWith(classOf[JUnitRunner])
+class ActionLoopContainerTests extends ActionProxyContainerTestUtils with WskActorSystem {
+
+  import GoResourceHelpers._
+
+  // "example" is the image build by /sdk/docker
+  def withActionLoopContainer(code: ActionContainer => Unit) = withContainer("actionloop")(code)
+
+  behavior of "actionloop"
+
+  def shCodeHello(main: String) = Seq(
+    Seq(main) ->
+      s"""#!/bin/bash
+         |while read line
+         |do
+         |   name="$$(echo $$line | jq -r .name)"
+         |   if test "$$name" == ""
+         |   then exit
+         |   fi
+         |   echo "name=$$name"
+         |   hello="Hello, $$name"
+         |   echo '{"${main}":"'$$hello'"}' >&3
+         |done
+         |""".stripMargin
+  )
+
+  private def helloMsg(name: String = "Demo") =
+    runPayload(JsObject("name" -> JsString(name)))
+
+  private def okMsg(key: String, value: String) =
+    200 -> Some(JsObject(key -> JsString(value)))
+
+
+  it should "run sample with init that does nothing" in {
+    val (out, err) = withActionLoopContainer { c =>
+      c.init(JsObject())._1 should be(200)
+      c.run(JsObject())._1 should be(400)
+    }
+  }
+
+
+  it should "deploy a shell script" in {
+    val script = shCodeHello("main")
+    val mesg = ExeBuilder.mkBase64Src(script, "main")
+    withActionLoopContainer {
+      c =>
+        val payload = initPayload(mesg)
+        c.init(payload)._1 should be(200)
+        c.run(helloMsg()) should be(okMsg("main", "Hello, Demo"))
+    }
+  }
+
+  it should "deploy a zip based script" in {
+    val scr = ExeBuilder.mkBase64SrcZip(shCodeHello("main"), "main")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(scr))._1 should be(200)
+        c.run(helloMsg()) should be(okMsg("main", "Hello, Demo"))
+    }
+  }
+ }
+
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala
new file mode 100644
index 0000000..e4c7320
--- /dev/null
+++ b/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.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.util.concurrent.TimeoutException
+import actionContainers.{ActionContainer, ActionProxyContainerTestUtils}
+import actionContainers.ActionContainer.withContainer
+import common.WskActorSystem
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+//import spray.json.JsNumber
+//import spray.json.JsBoolean
+import spray.json.{JsObject, JsString}
+
+@RunWith(classOf[JUnitRunner])
+class ActionLoopGoContainerTests extends ActionProxyContainerTestUtils with WskActorSystem {
+
+  import GoResourceHelpers._
+
+  val goCompiler = "actionloop-golang-v1.10"
+  val image = goCompiler
+
+  def withActionLoopContainer(code: ActionContainer => Unit) = withContainer(image)(code)
+
+  behavior of image
+
+
+  private def checkresponse(res: Option[JsObject], args: JsObject = JsObject()) = {
+    res shouldBe defined
+    res.get.fields("error") shouldBe JsString("no action defined yet")
+    //res.get.fields("args") shouldBe args
+  }
+
+  private def goCodeHello(file: String, main: String) = Seq(
+    Seq(s"${file}.go") ->
+      s"""
+         |package action
+         |
+         |import (
+         |	"encoding/json"
+         |	"fmt"
+         |)
+         |
+         |func ${main}(event json.RawMessage) (json.RawMessage, error) {
+         |	var obj map[string]interface{}
+         |	json.Unmarshal(event, &obj)
+         |	name, ok := obj["name"].(string)
+         |	if !ok {
+         |		name = "Stranger"
+         |	}
+         |	fmt.Printf("name=%s\\n", name)
+         |	msg := map[string]string{"${file}-${main}": ("Hello, " + name + "!")}
+         |	return json.Marshal(msg)
+         |}
+         |
+          """.stripMargin
+  )
+
+  private def helloMsg(name: String = "Demo") =
+    runPayload(JsObject("name" -> JsString(name)))
+
+  private def okMsg(key: String, value: String) =
+    200 -> Some(JsObject(key -> JsString(value)))
+
+
+  it should "run sample with init that does nothing" in {
+    val (out, err) = withActionLoopContainer { c =>
+      c.init(JsObject())._1 should be(200)
+      c.run(JsObject())._1 should be(400)
+    }
+  }
+
+  it should "accept a binary main" in {
+    val exe = ExeBuilder.mkBase64Exe(
+      goCompiler, goCodeHello("main", "Main"), "main")
+
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(exe))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("main-Main", "Hello, Demo!"))
+    }
+  }
+
+  //def pr(x: Any) = { println(x) ; x}
+
+  it should "build and run a go main zipped exe" in {
+    val zip = ExeBuilder.mkBase64Zip(
+      goCompiler, goCodeHello("main", "Main"), "main")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(zip))._1 should be(200)
+        c.run(helloMsg()) should be(okMsg("main-Main", "Hello, Demo!"))
+    }
+  }
+
+  it should "buid and run a go hello exe " in {
+    val exe = ExeBuilder.mkBase64Exe(
+      goCompiler, goCodeHello("hello", "Hello"), "hello")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(exe, "hello"))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("hello-Hello", "Hello, Demo!"))
+    }
+  }
+
+  it should "build and run a go hello zipped exe" in {
+    val zip = ExeBuilder.mkBase64Zip(
+      goCompiler, goCodeHello("hello", "Hello"), "hello")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(zip, "hello"))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("hello-Hello", "Hello, Demo!"))
+    }
+  }
+
+  val helloSrc =
+    """
+      |package action
+      |
+      |import (
+      |	"encoding/json"
+      |	"fmt"
+      |)
+      |
+      |func Hello(event json.RawMessage) (json.RawMessage, error) {
+      |	var obj struct {
+      |		Name string `json:",omitempty"`
+      |	}
+      |	err := json.Unmarshal(event, &obj)
+      |	if err != nil {
+      |		return nil, err
+      |	}
+      |	name := obj.Name
+      |	if name == "" {
+      |		name = "Stranger"
+      |	}
+      |	fmt.Printf("name=%s\n", name)
+      |	msg := map[string]string{"Hello": ("Hello, " + name + "!")}
+      |	return json.Marshal(msg)
+      |}
+    """.stripMargin
+
+  val mainSrc =
+    """
+      |package action
+      |
+      |import (
+      |	"encoding/json"
+      |	"fmt"
+      |)
+      |
+      |func Main(event json.RawMessage) (json.RawMessage, error) {
+      |	var obj map[string]interface{}
+      |	json.Unmarshal(event, &obj)
+      |	name, ok := obj["name"].(string)
+      |	if !ok {
+      |		name = "Stranger"
+      |	}
+      |	fmt.Printf("name=%s\n", name)
+      |	msg := map[string]string{"Main": ("Hello, " + name + "!")}
+      |	return json.Marshal(msg)
+      |}
+    """.stripMargin
+
+  it should "deploy a src main action " in {
+    var src = ExeBuilder.mkBase64Src(Seq(
+      Seq("main") -> mainSrc
+    ), "main")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(src))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("Main", "Hello, Demo!"))
+    }
+  }
+
+  it should "deploy a src hello action " in {
+    var src = ExeBuilder.mkBase64Src(Seq(
+      Seq("hello") -> helloSrc
+    ), "hello")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(src, "hello"))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("Hello", "Hello, Demo!"))
+    }
+  }
+
+  it should "deploy a zip main src action" in {
+    var src = ExeBuilder.mkBase64SrcZip(Seq(
+      Seq("main.go") -> mainSrc
+    ), "main")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(src))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("Main", "Hello, Demo!"))
+    }
+  }
+
+  it should "deploy a zip main src subdir action" in {
+    var src = ExeBuilder.mkBase64SrcZip(Seq(
+      Seq("action", "main.go") -> mainSrc
+    ), "main")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(src))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("Main", "Hello, Demo!"))
+    }
+  }
+
+  it should "deploy a zip src hello action " in {
+    var src = ExeBuilder.mkBase64SrcZip(Seq(
+      Seq("hello.go") -> helloSrc
+    ), "hello")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(src, "hello"))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("Hello", "Hello, Demo!"))
+    }
+  }
+
+
+  it should "deploy a zip src hello action in subdir" in {
+    var src = ExeBuilder.mkBase64SrcZip(Seq(
+      Seq("action", "hello.go") -> helloSrc
+    ), "hello")
+    withActionLoopContainer {
+      c =>
+        c.init(initPayload(src, "hello"))._1 shouldBe (200)
+        c.run(helloMsg()) should be(okMsg("Hello", "Hello, Demo!"))
+    }
+  }
+}
+
diff --git a/tests/src/test/scala/runtime/actionContainers/GoResourceHelpers.scala b/tests/src/test/scala/runtime/actionContainers/GoResourceHelpers.scala
new file mode 100644
index 0000000..c001f22
--- /dev/null
+++ b/tests/src/test/scala/runtime/actionContainers/GoResourceHelpers.scala
@@ -0,0 +1,207 @@
+/*
+ * 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.net.URI
+import java.nio.file._
+import java.nio.charset.StandardCharsets
+import java.nio.file.attribute.BasicFileAttributes
+
+import collection.JavaConverters._
+import actionContainers.ResourceHelpers
+
+object GoResourceHelpers {
+
+
+  /** Create a temporary directory in your /tmp directory.
+    *
+    * This is needed to use docker volume mounts.
+    * On mac I need to use the /tmp directory,
+    * because the default folder used by gradle under Mac
+    * is not accessible by default by Docker for Mac
+    *
+    */
+  def tmpDirectoryFile(prefix: String, suffix: String = "") =
+    new File(new File("/tmp", "openwhisk"), prefix+System.currentTimeMillis().toString+suffix)
+
+  def createTmpDirectory(prefix: String, suffix: String = "") = {
+    val tmpDir = tmpDirectoryFile(prefix,suffix)
+    tmpDir.mkdirs()
+    tmpDir.toPath.toAbsolutePath
+  }
+
+  private def makeZipFromDir(dir: Path): Path = makeArchiveFromDir(dir, ".zip")
+
+  private def makeJarFromDir(dir: Path): Path = makeArchiveFromDir(dir, ".jar")
+
+  /**
+    * Compresses all files beyond a directory into a zip file.
+    * Note that Jar files are just zip files.
+    */
+  private def makeArchiveFromDir(dir: Path, extension: String): Path = {
+    // Any temporary file name for the archive.
+    val arPath = createTmpDirectory("output", extension).toAbsolutePath()
+
+    // We "mount" it as a filesystem, so we can just copy files into it.
+    val dstUri = new URI("jar:" + arPath.toUri().getScheme(), arPath.toAbsolutePath().toString(), null)
+    // OK, that's a hack. Doing this because newFileSystem wants to create that file.
+    arPath.toFile().delete()
+    val fs = FileSystems.newFileSystem(dstUri, Map(("create" -> "true")).asJava)
+
+    // Traversing all files in the bin directory...
+    Files.walkFileTree(
+      dir,
+      new SimpleFileVisitor[Path]() {
+        override def visitFile(path: Path, attributes: BasicFileAttributes) = {
+          // The path relative to the src dir
+          val relPath = dir.relativize(path)
+
+          // The corresponding path in the zip
+          val arRelPath = fs.getPath(relPath.toString())
+
+          // If this file is not top-level in the src dir...
+          if (relPath.getParent() != null) {
+            // ...create the directory structure if it doesn't exist.
+            if (!Files.exists(arRelPath.getParent())) {
+              Files.createDirectories(arRelPath.getParent())
+            }
+          }
+
+          // Finally we can copy that file.
+          Files.copy(path, arRelPath)
+
+          FileVisitResult.CONTINUE
+        }
+      })
+
+    fs.close()
+
+    arPath
+  }
+
+
+  /**
+    * Creates a temporary directory in the home and reproduces the desired file structure
+    * in it. Returns the path of the temporary directory and the path of each
+    * file as represented in it.
+    *
+    * NOTE this is different from writeSourcesToTempDirectory because it uses
+    * a tmp folder in the home directory.
+    *
+    * */
+  private def writeSourcesToHomeTmpDirectory(sources: Seq[(Seq[String], String)]): (Path, Seq[Path]) = {
+    // A temporary directory for the source files.
+    val srcDir = createTmpDirectory("src")
+    val srcAbsPaths = for ((sourceName, sourceContent) <- sources) yield {
+      // The relative path of the source file
+      val srcRelPath = Paths.get(sourceName.head, sourceName.tail: _*)
+      // The absolute path of the source file
+      val srcAbsPath = srcDir.resolve(srcRelPath)
+      // Create parent directories if needed.
+      Files.createDirectories(srcAbsPath.getParent)
+      // Writing contents
+      Files.write(srcAbsPath, sourceContent.getBytes(StandardCharsets.UTF_8))
+
+      srcAbsPath
+    }
+
+    (srcDir, srcAbsPaths)
+  }
+
+  /**
+    * Builds executables using docker images as compilers.
+    * Images are assumed to be able to be run as
+    * docker <image> -v <sources>:/src -v <output>:/out compile <main>
+    * The compiler will read sources from /src and leave the final binary in /out/<main>
+    * <main> is also the name of the main function to be invoked
+    * Implementations available for swift and go
+    */
+  object ExeBuilder {
+
+    private lazy val dockerBin: String = {
+      List("/usr/bin/docker", "/usr/local/bin/docker").find { bin =>
+        new File(bin).isFile
+      }.get // This fails if the docker binary couldn't be located.
+    }
+
+    // prepare sources, then compile them
+    // return the exe File  and the output dir Path
+    private def compile(image: String, sources: Seq[(Seq[String], String)], main: String) = {
+      require(!sources.isEmpty)
+
+      // The absolute paths of the source file
+      val (srcDir, srcAbsPaths) = writeSourcesToHomeTmpDirectory(sources)
+      val src = srcDir.toFile.getAbsolutePath
+
+      // A temporary directory for the destination files.
+      // DO NOT CREATE IT IN ADVANCE or you will get a permission denied
+      val outDir = tmpDirectoryFile("out")
+      val out = outDir.toPath.toAbsolutePath
+
+      // command to compile
+      val exe = new File(outDir, main)
+
+      val cmd = s"${dockerBin} run " +
+        s"-v ${src}:/src " +
+        s"-v ${out}:/out:rw " +
+        s"${image} compile ${main}"
+
+      // compiling
+      import sys.process._
+      cmd.!
+
+      // result
+      exe -> outDir.toPath
+
+    }
+
+    def mkBase64Exe(image: String, sources: Seq[(Seq[String], String)], main: String) = {
+      val (exe, dir) = compile(image, sources, main)
+      //println(s"exe=${exe.getAbsolutePath}")
+      ResourceHelpers.readAsBase64(exe.toPath)
+    }
+
+    def mkBase64Zip(image: String, sources: Seq[(Seq[String], String)], main: String) = {
+      val (exe, dir) = compile(image, sources, main)
+      val archive = makeZipFromDir(dir)
+      //println(s"zip=${archive.toFile.getAbsolutePath}")
+      ResourceHelpers.readAsBase64(archive)
+    }
+
+    def mkBase64Src(sources: Seq[(Seq[String], String)], main: String) = {
+      val (srcDir, srcAbsPaths) = writeSourcesToHomeTmpDirectory(sources)
+      val file = new File(srcDir.toFile, main)
+      //println(file)
+      ResourceHelpers.readAsBase64(file.toPath)
+    }
+
+    def mkBase64SrcZip(sources: Seq[(Seq[String], String)], main: String) = {
+      val (srcDir, srcAbsPaths) = writeSourcesToHomeTmpDirectory(sources)
+      //println(srcDir)
+      val archive = makeZipFromDir(srcDir)
+      ResourceHelpers.readAsBase64(archive)
+    }
+  }
+
+  def writeFile(name: String, body: String): Unit = {
+    val fw = new java.io.FileWriter(name)
+    fw.write(body)
+    fw.close
+  }
+}
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index 037256d..450540d 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -27,16 +27,21 @@ UTILDIR="$ROOTDIR/../incubator-openwhisk-utilities"
 
 export OPENWHISK_HOME=$WHISKDIR
 
-IMAGE_PREFIX="testing"
-
 # run scancode using the ASF Release configuration
 cd $UTILDIR
 scancode/scanCode.py --config scancode/ASF-Release.cfg $ROOTDIR
 
-cd $ROOTDIR
+# Build OpenWhisk deps before we run tests
+cd $WHISKDIR
+TERM=dumb ./gradlew install
+# Mock file (works around bug upstream)
+echo "openwhisk.home=$WHISKDIR" > whisk.properties
+echo "vcap.services.file=" >> whisk.properties
 
 # Build/Compile go
-TERM=dumb ./gradlew build
+cd $ROOTDIR
+# compile without testing as we need docker images first
+TERM=dumb ./gradlew build -x test
+# ok now you can build docker images using the compiled proxy
+TERM=dumb ./gradlew distDocker
 
-# Build runtime image
-TERM=dumb ./gradlew distDocker -PdockerImagePrefix=${IMAGE_PREFIX}
diff --git a/tools/travis/setup.sh b/tools/travis/setup.sh
index 17e7285..fa7ffeb 100755
--- a/tools/travis/setup.sh
+++ b/tools/travis/setup.sh
@@ -18,6 +18,10 @@
 
 set -e
 
+# add realpath
+sudo apt-get -y update
+sudo apt-get -y install realpath
+
 # Build script for Travis-CI.
 
 SCRIPTDIR=$(cd $(dirname "$0") && pwd)
@@ -28,5 +32,7 @@ HOMEDIR="$SCRIPTDIR/../../../"
 cd $HOMEDIR
 git clone https://github.com/apache/incubator-openwhisk-utilities.git
 
-# add realpath
-sudo apt-get -y update && sudo apt-get -y install realpath
+# clone main openwhisk repo. for testing purposes
+git clone --depth=1 https://github.com/apache/incubator-openwhisk.git openwhisk
+cd openwhisk
+./tools/travis/setup.sh
diff --git a/tools/travis/test.sh b/tools/travis/test.sh
index 81ab042..2534d83 100755
--- a/tools/travis/test.sh
+++ b/tools/travis/test.sh
@@ -22,9 +22,11 @@ set -ex
 
 SCRIPTDIR=$(cd $(dirname "$0") && pwd)
 ROOTDIR="$SCRIPTDIR/../.."
+WHISKDIR="$ROOTDIR/../openwhisk"
 
+export OPENWHISK_HOME=$WHISKDIR
 cd ${ROOTDIR}
-TERM=dumb ./gradlew test --info
-
+TERM=dumb ./gradlew :tests:test
 
+TERM=dumb ./gradlew test --info
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services