You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by ms...@apache.org on 2019/05/10 12:29:35 UTC

[incubator-openwhisk-runtime-go] branch master updated: Go12 jar support (#88)

This is an automated email from the ASF dual-hosted git repository.

msciabarra pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-runtime-go.git


The following commit(s) were added to refs/heads/master by this push:
     new 1cbb963  Go12 jar support (#88)
1cbb963 is described below

commit 1cbb96383502ca6df45058d966927c0796c31fbd
Author: Michele Sciabarra <30...@users.noreply.github.com>
AuthorDate: Fri May 10 14:29:30 2019 +0200

    Go12 jar support (#88)
    
    * supporting jars as is for java runtime
    
    * implementing go 1.12
    
    * do not use goBuild any more
    
    * get some libs
---
 .gitignore                                         |   2 +
 CHANGES.md                                         |   5 +
 actionloop/build.gradle                            |   3 +
 build.gradle                                       |  27 -----
 common/gobuild.py                                  |   3 +-
 go.mod                                             |   5 +
 go.sum                                             |   7 ++
 golang1.11/build.gradle                            |  14 ++-
 golang1.12/Dockerfile                              |  21 ++++
 {golang1.11 => golang1.12}/build.gradle            |  17 ++-
 openwhisk/_test/build.sh                           |   4 +
 openwhisk/_test/jar/META-INF/MANIFEST.MF           |   4 +
 openwhisk/_test/jar/hello.txt                      |   2 +
 openwhisk/compiler.go                              |   1 +
 openwhisk/extractor.go                             |   6 +
 openwhisk/extractor_test.go                        |  25 +++++
 openwhisk/filetype.go                              |   1 +
 openwhisk/initHandler.go                           |   3 +-
 openwhisk/runHandler.go                            |   2 +-
 openwhisk/util_test.go                             |   4 +-
 openwhisk/version.go                               |   2 +-
 openwhisk/zip.go                                   |  30 ++++-
 openwhisk/zip_test.go                              |  18 ++-
 settings.gradle                                    |   1 +
 .../ActionLoopBasicGo12Tests.scala                 | 125 +++++++++++++++++++++
 ...ts.scala => ActionLoopGo12ContainerTests.scala} |  12 +-
 .../ActionLoopGoContainerTests.scala               |   6 +-
 tools/travis/build.sh                              |   4 +-
 tools/travis/setup.sh                              |   2 +
 tools/travis/test.sh                               |   5 +-
 30 files changed, 300 insertions(+), 61 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7eacee2..6862d66 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ vendor/
 common/proxy
 actionloop/proxy
 golang1.11/proxy
+golang1.12/proxy
 
 # Go test transient files
 openwhisk/_test/exec
@@ -22,6 +23,7 @@ openwhisk/_test/hi
 openwhisk/_test/hello_greeting
 openwhisk/_test/hello_message
 openwhisk/_test/*.zip
+openwhisk/_test/*.jar
 openwhisk/_test/compile/
 openwhisk/_test/output/
 openwhisk/action/
diff --git a/CHANGES.md b/CHANGES.md
index c9a557b..a2c8710 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -31,3 +31,8 @@ ActionLoop for Scripting Languages
 - any script starting with '#!' is recognized as executable
 - now the -compile will zip the entire directory of the `bin` directory after compilation
 - if you upload a folder `src/exec` the entire directory is moved to `bin`, including other uploaded files
+- Support for Go 1.12.4
+- Support for jar not expanded for Java when set OW_SAVE_JAR
+- You can initalize multiple times when debugging
+- Removed gogradle plugin, now building directly with go
+
diff --git a/actionloop/build.gradle b/actionloop/build.gradle
index 00b18da..5464137 100644
--- a/actionloop/build.gradle
+++ b/actionloop/build.gradle
@@ -23,6 +23,9 @@ distDocker.finalizedBy('cleanup')
 
 task staticBuildProxy(type: Exec) {
 	environment CGO_ENABLED: "0"
+	environment GOOS: "linux"
+	environment GOARCH: "amd64"
+
 	commandLine 'go', 'build',
 		'-o',  'proxy', '-a',
 		'-ldflags', '-extldflags "-static"',
diff --git a/build.gradle b/build.gradle
index c4d7384..26f542d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,35 +24,8 @@ buildscript {
     }
 }
 
-plugins {
-    id 'com.github.blindpirate.gogradle' version '0.8.1'
-}
-
-dependencies {
-    golang {
-        build 'github.com/sirupsen/logrus@v1.1.0'
-        test 'github.com/stretchr/testify@v1.2.1'
-    }
-}
-
-
 subprojects {
     apply plugin: 'scalafmt'
     scalafmt.configFilePath = gradle.scalafmt.config
 }
 
-golang {
-  packagePath = 'github.com/apache/incubator-openwhisk-runtime-go'
-  goVersion = '1.11.6'
-}
-
-build.dependsOn vendor
-
-build {
-  targetPlatform = ['linux-amd64']
-  go """build -o common/proxy -ldflags '-extldflags "-static"'  main/proxy.go"""
-}
-
-task cleanup(type: Delete) {
-    delete 'common/proxy'
-}
diff --git a/common/gobuild.py b/common/gobuild.py
index 8cd3cf0..f86f7cb 100755
--- a/common/gobuild.py
+++ b/common/gobuild.py
@@ -55,7 +55,8 @@ def build(parent, source_dir, target):
     # compile...
     env = {
       "PATH": os.environ["PATH"],
-      "GOPATH": os.path.abspath(parent)
+      "GOPATH": os.path.abspath(parent),
+      "GOCACHE": "/tmp"
     }
     if os.path.isdir("%s/main" % source_dir):
         source_dir += "/main"
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..1cd20fd
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module github.com/apache/incubator-openwhisk-runtime-go
+
+go 1.12
+
+require github.com/stretchr/testify v1.3.0
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..4347755
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,7 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
diff --git a/golang1.11/build.gradle b/golang1.11/build.gradle
index cfe8e61..04c8064 100644
--- a/golang1.11/build.gradle
+++ b/golang1.11/build.gradle
@@ -18,14 +18,20 @@
 ext.dockerImageName = 'actionloop-golang-v1.11'
 apply from: '../gradle/docker.gradle'
 
-distDocker.dependsOn 'copyProxy'
+distDocker.dependsOn 'staticBuildProxy'
 distDocker.dependsOn 'copyCompiler'
 distDocker.dependsOn 'copyEpilogue'
 distDocker.finalizedBy('cleanup')
 
-task copyProxy(type: Copy) {
-    from '../common/proxy'
-    into '.'
+task staticBuildProxy(type: Exec) {
+	environment CGO_ENABLED: "0"
+	environment GOOS: "linux"
+	environment GOARCH: "amd64"
+
+	commandLine 'go', 'build',
+		'-o',  'proxy', '-a',
+		'-ldflags', '-extldflags "-static"',
+		'../main/proxy.go'
 }
 
 task copyCompiler(type: Copy) {
diff --git a/golang1.12/Dockerfile b/golang1.12/Dockerfile
new file mode 100644
index 0000000..9284f7c
--- /dev/null
+++ b/golang1.12/Dockerfile
@@ -0,0 +1,21 @@
+FROM golang:1.12.4
+RUN echo "deb http://deb.debian.org/debian stretch-backports main contrib non-free" \
+     >>/etc/apt/sources.list &&\
+    apt-get update && apt-get install -y \
+     curl \
+     jq \
+     git \
+     realpath &&\
+    apt-get -y install \
+     librdkafka1=0.11.6-1~bpo9+1 \
+     librdkafka++1=0.11.6-1~bpo9+1 && \
+    apt-get -y install \
+     librdkafka-dev=0.11.6-1~bpo9+1 && \
+    rm -rf /var/lib/apt/lists/*
+RUN mkdir /action
+WORKDIR /action
+ADD proxy /bin/proxy
+ADD gobuild.py /bin/compile
+ADD gobuild.py.launcher.go /bin/compile.launcher.go
+ENV OW_COMPILER=/bin/compile
+ENTRYPOINT [ "/bin/proxy" ]
diff --git a/golang1.11/build.gradle b/golang1.12/build.gradle
similarity index 79%
copy from golang1.11/build.gradle
copy to golang1.12/build.gradle
index cfe8e61..f5e0043 100644
--- a/golang1.11/build.gradle
+++ b/golang1.12/build.gradle
@@ -15,19 +15,26 @@
  * limitations under the License.
  */
 
-ext.dockerImageName = 'actionloop-golang-v1.11'
+ext.dockerImageName = 'actionloop-golang-v1.12'
 apply from: '../gradle/docker.gradle'
 
-distDocker.dependsOn 'copyProxy'
+distDocker.dependsOn 'staticBuildProxy'
 distDocker.dependsOn 'copyCompiler'
 distDocker.dependsOn 'copyEpilogue'
 distDocker.finalizedBy('cleanup')
 
-task copyProxy(type: Copy) {
-    from '../common/proxy'
-    into '.'
+task staticBuildProxy(type: Exec) {
+	environment CGO_ENABLED: "0"
+	environment GOOS: "linux"
+	environment GOARCH: "amd64"
+
+	commandLine 'go', 'build',
+		'-o',  'proxy', '-a',
+		'-ldflags', '-extldflags "-static"',
+		'../main/proxy.go'
 }
 
+
 task copyCompiler(type: Copy) {
     from '../common/gobuild.py'
     into '.'
diff --git a/openwhisk/_test/build.sh b/openwhisk/_test/build.sh
index 42707f8..1922b73 100755
--- a/openwhisk/_test/build.sh
+++ b/openwhisk/_test/build.sh
@@ -51,6 +51,10 @@ cd src
 zip -q -r ../hello.zip main.go hello
 cd ..
 
+test -e sample.jar && rm sample.jar
+cd jar ; zip -q -r ../sample.jar * ; cd ..
+
 build exec
 test -e exec.zip && rm exec.zip
 zip -q -r exec.zip exec etc dir
+
diff --git a/openwhisk/_test/jar/META-INF/MANIFEST.MF b/openwhisk/_test/jar/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..eb1ebe1
--- /dev/null
+++ b/openwhisk/_test/jar/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements; and to You under the Apache License, Version 2.0.
+Manifest-Version: 1.0
+Created-By: 1.8.0_191 (Oracle Corporation)
diff --git a/openwhisk/_test/jar/hello.txt b/openwhisk/_test/jar/hello.txt
new file mode 100755
index 0000000..e4e2475
--- /dev/null
+++ b/openwhisk/_test/jar/hello.txt
@@ -0,0 +1,2 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor
+# license agreements; and to You under the Apache License, Version 2.0.
diff --git a/openwhisk/compiler.go b/openwhisk/compiler.go
index f03c30d..686c5e2 100644
--- a/openwhisk/compiler.go
+++ b/openwhisk/compiler.go
@@ -27,6 +27,7 @@ import (
 
 // check if the file exists and it is already compiled
 func isCompiled(file string) bool {
+	Debug("IsCompiled? %s", file)
 	_, err := os.Stat(file)
 	if err != nil {
 		return false
diff --git a/openwhisk/extractor.go b/openwhisk/extractor.go
index f750fc6..097de0a 100644
--- a/openwhisk/extractor.go
+++ b/openwhisk/extractor.go
@@ -56,6 +56,12 @@ func (ap *ActionProxy) ExtractAction(buf *[]byte, suffix string) (string, error)
 	os.MkdirAll(newDir, 0755)
 	file := newDir + "/exec"
 	if IsZip(*buf) {
+		jar := os.Getenv("OW_SAVE_JAR")
+		if jar != "" {
+			jarFile := newDir + "/" + jar
+			Debug("Extract Action, checking if it is a jar first")
+			return jarFile, UnzipOrSaveJar(*buf, newDir, jarFile)
+		}
 		Debug("Extract Action, assuming a zip")
 		return file, Unzip(*buf, newDir)
 	}
diff --git a/openwhisk/extractor_test.go b/openwhisk/extractor_test.go
index c3009ad..007c6d6 100644
--- a/openwhisk/extractor_test.go
+++ b/openwhisk/extractor_test.go
@@ -60,6 +60,7 @@ func TestExtractActionTest_zip(t *testing.T) {
 
 func TestExtractAction_script(t *testing.T) {
 	log, _ := ioutil.TempFile("", "log")
+	assert.Nil(t, os.RemoveAll("./action/x4"))
 	ap := NewActionProxy("./action/x4", "", log, log)
 	buf := []byte("#!/bin/sh\necho ok")
 	_, err := ap.ExtractAction(&buf, "bin")
@@ -67,6 +68,30 @@ func TestExtractAction_script(t *testing.T) {
 	assert.Nil(t, err)
 }
 
+func TestExtractAction_save_jar(t *testing.T) {
+	os.Setenv("OW_SAVE_JAR", "exec.jar")
+	log, _ := ioutil.TempFile("", "log")
+	assert.Nil(t, os.RemoveAll("./action/x5"))
+	ap := NewActionProxy("./action/x5", "", log, log)
+	file, _ := ioutil.ReadFile("_test/sample.jar")
+	_, err := ap.ExtractAction(&file, "bin")
+	assert.Nil(t, exists("./action/x5", "bin/exec.jar"))
+	assert.Nil(t, err)
+	os.Setenv("OW_SAVE_JAR", "")
+}
+
+func TestExtractAction_extract_jar(t *testing.T) {
+	os.Setenv("OW_SAVE_JAR", "")
+	log, _ := ioutil.TempFile("", "log")
+	assert.Nil(t, os.RemoveAll("./action/x6"))
+	ap := NewActionProxy("./action/x6", "", log, log)
+	file, _ := ioutil.ReadFile("_test/sample.jar")
+	_, err := ap.ExtractAction(&file, "bin")
+	assert.Nil(t, exists("./action/x6", "bin/META-INF/MANIFEST.MF"))
+	assert.Nil(t, err)
+}
+
+
 func TestHighestDir(t *testing.T) {
 	assert.Equal(t, highestDir("./_test"), 0)
 	assert.Equal(t, highestDir("./_test/first"), 3)
diff --git a/openwhisk/filetype.go b/openwhisk/filetype.go
index 4825837..20fe388 100644
--- a/openwhisk/filetype.go
+++ b/openwhisk/filetype.go
@@ -45,6 +45,7 @@ func IsBangPath(buf []byte) bool {
 
 // IsExecutable check if it is an executable, according the current runtime
 func IsExecutable(buf []byte, runtime string) bool {
+	Debug("checking executable for %s", runtime)
 	switch runtime {
 	case "darwin":
 		return IsMach64(buf) || IsBangPath(buf)
diff --git a/openwhisk/initHandler.go b/openwhisk/initHandler.go
index 474e85c..1929c4f 100644
--- a/openwhisk/initHandler.go
+++ b/openwhisk/initHandler.go
@@ -51,7 +51,8 @@ func sendOK(w http.ResponseWriter) {
 
 func (ap *ActionProxy) initHandler(w http.ResponseWriter, r *http.Request) {
 
-	if ap.initialized {
+	// you can do muliple initializations when debugging
+	if ap.initialized && !Debugging {
 		msg := "Cannot initialize the action more than once."
 		sendError(w, http.StatusForbidden, msg)
 		log.Println(msg)
diff --git a/openwhisk/runHandler.go b/openwhisk/runHandler.go
index 3345cb9..3a16781 100644
--- a/openwhisk/runHandler.go
+++ b/openwhisk/runHandler.go
@@ -35,7 +35,7 @@ func sendError(w http.ResponseWriter, code int, cause string) {
 	b, err := json.Marshal(errResponse)
 	if err != nil {
 		b = []byte("error marshalling error response")
-		fmt.Println(b, err)
+		Debug(err.Error())
 	}
 	w.Header().Set("Content-Type", "application/json")
 	w.WriteHeader(code)
diff --git a/openwhisk/util_test.go b/openwhisk/util_test.go
index 19a0d4c..586520a 100644
--- a/openwhisk/util_test.go
+++ b/openwhisk/util_test.go
@@ -170,8 +170,8 @@ func removeLineNr(out string) string {
 	return re.ReplaceAllString(out, "::")
 }
 func TestMain(m *testing.M) {
-	var Debug = false // enable debug of tests
-	if !Debug {
+	Debugging = false // enable debug of tests
+	if !Debugging {
 		// silence those annoying tests
 		log.SetOutput(ioutil.Discard)
 		// build support files
diff --git a/openwhisk/version.go b/openwhisk/version.go
index 3640360..7b9a646 100644
--- a/openwhisk/version.go
+++ b/openwhisk/version.go
@@ -17,4 +17,4 @@
 package openwhisk
 
 // Version number - internal
-var Version = "2"
+var Version = "2.1"
diff --git a/openwhisk/zip.go b/openwhisk/zip.go
index 36ae387..5f97696 100644
--- a/openwhisk/zip.go
+++ b/openwhisk/zip.go
@@ -19,20 +19,44 @@ package openwhisk
 import (
 	"archive/zip"
 	"bytes"
+	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
 	"strings"
 )
 
-// Unzip extracts file and directories in the given destination folder
-func Unzip(src []byte, dest string) error {
+func openZip(src []byte) *zip.Reader {
 	reader := bytes.NewReader(src)
 	r, err := zip.NewReader(reader, int64(len(src)))
 	if err != nil {
-		return err
+		return nil
 	}
+	return r
+}
+
+// UnzipOrSaveJar checks if is is a jar file looking if there is a META-INF folder in it
+// if it is a jar file, save it as the file jarFile
+// Otherwise unzip the files in the destination dir
+func UnzipOrSaveJar(src []byte, dest string, jarFile string) error {
+	r := openZip(src)
+	if r == nil {
+		return fmt.Errorf("not a zip file")
+	}
+	for _, f := range r.File {
+		if f.Name == "META-INF/MANIFEST.MF" {
+			ioutil.WriteFile(jarFile, src, 0644)
+			return nil
+		}
+	}
+	return Unzip(src, dest)
+}
+
+// Unzip extracts file and directories in the given destination folder
+func Unzip(src []byte, dest string) error {
+	r := openZip(src)
 	os.MkdirAll(dest, 0755)
 	// Closure to address file descriptors issue with all the deferred .Close() methods
 	extractAndWriteFile := func(f *zip.File) error {
diff --git a/openwhisk/zip_test.go b/openwhisk/zip_test.go
index a2c8eef..f386ef0 100644
--- a/openwhisk/zip_test.go
+++ b/openwhisk/zip_test.go
@@ -21,12 +21,12 @@ import (
 	"os"
 )
 
-func Example() {
+func Example_zip() {
 	os.RemoveAll("./action/unzip")
 	os.Mkdir("./action/unzip", 0755)
 	buf, err := Zip("_test/pysample")
 	fmt.Println(err)
-	err = Unzip(buf, "./action/unzip")
+	err = UnzipOrSaveJar(buf, "./action/unzip", "./action/unzip/exec.jar")
 	sys("_test/find.sh", "./action/unzip")
 	fmt.Println(err)
 	// Output:
@@ -40,3 +40,17 @@ func Example() {
 	// ./action/unzip/lib/exec.py
 	// <nil>
 }
+func Example_jar() {
+	os.RemoveAll("./action/unzip")
+	os.Mkdir("./action/unzip", 0755)
+	buf, err := Zip("_test/jar")
+	fmt.Println(err)
+	err = UnzipOrSaveJar(buf, "./action/unzip", "./action/unzip/exec.jar")
+	sys("_test/find.sh", "./action/unzip")
+	fmt.Println(err)
+	// Output:
+	// <nil>
+	// ./action/unzip
+	// ./action/unzip/exec.jar
+	// <nil>
+}
diff --git a/settings.gradle b/settings.gradle
index 15eaa52..f202675 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -19,6 +19,7 @@ include 'tests'
 
 include 'actionloop'
 include 'golang1.11'
+include 'golang1.12'
 
 rootProject.name = 'runtime-golang'
 
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGo12Tests.scala b/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGo12Tests.scala
new file mode 100644
index 0000000..7c38472
--- /dev/null
+++ b/tests/src/test/scala/runtime/actionContainers/ActionLoopBasicGo12Tests.scala
@@ -0,0 +1,125 @@
+/*
+ * 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 actionContainers.ActionContainer.withContainer
+import actionContainers.{ActionContainer, BasicActionRunnerTests}
+import common.WskActorSystem
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class ActionLoopBasicGo12Tests
+    extends BasicActionRunnerTests
+    with WskActorSystem {
+
+  val goCompiler = "actionloop-golang-v1.12"
+  val image = goCompiler
+
+  override def withActionContainer(env: Map[String, String] = Map.empty)(
+      code: ActionContainer => Unit) = {
+    withContainer(image, env)(code)
+  }
+
+  def withActionLoopContainer(code: ActionContainer => Unit) =
+    withContainer(image)(code)
+
+  behavior of image
+
+  override val testNoSourceOrExec = TestConfig("")
+
+  override val testNotReturningJson = TestConfig(
+    """
+      |package main
+      |import (
+      |	"bufio"
+      |	"fmt"
+      |	"os"
+      |)
+      |func main() {
+      |	reader := bufio.NewReader(os.Stdin)
+      |	out := os.NewFile(3, "pipe")
+      |	defer out.Close()
+      |	reader.ReadBytes('\n')
+      |	fmt.Fprintln(out, "\"a string but not a map\"")
+      |	reader.ReadBytes('\n')
+      |}
+    """.stripMargin)
+
+  override val testEcho = TestConfig(
+    """|package main
+       |import "fmt"
+       |import "log"
+       |func Main(args map[string]interface{}) map[string]interface{} {
+       | fmt.Println("hello stdout")
+       | log.Println("hello stderr")
+       | return args
+       |}
+    """.stripMargin)
+
+  override val testUnicode = TestConfig(
+    """|package main
+       |import "fmt"
+       |func Main(args map[string]interface{}) map[string]interface{} {
+       |	delimiter := args["delimiter"].(string)
+       |	str := delimiter + " ☃ " + delimiter
+       |  fmt.Println(str)
+       |	res := make(map[string]interface{})
+       |	res["winter"] = str
+       |	return res
+       |}
+       """.stripMargin)
+
+  override val testEnv = TestConfig(
+    """
+      |package main
+      |import "os"
+      |func Main(args map[string]interface{}) map[string]interface{} {
+      |	res := make(map[string]interface{})
+      |	res["api_host"] = os.Getenv("__OW_API_HOST")
+      |	res["api_key"] = os.Getenv("__OW_API_KEY")
+      |	res["namespace"] = os.Getenv("__OW_NAMESPACE")
+      |	res["action_name"] = os.Getenv("__OW_ACTION_NAME")
+      |	res["activation_id"] = os.Getenv("__OW_ACTIVATION_ID")
+      |	res["deadline"] = os.Getenv("__OW_DEADLINE")
+      |	return res
+      |}
+    """.stripMargin)
+
+  override val testInitCannotBeCalledMoreThanOnce = TestConfig(
+    """|package main
+       |func Main(args map[string]interface{}) map[string]interface{} {
+       | return args
+       |}
+    """.stripMargin)
+
+  override val testEntryPointOtherThanMain = TestConfig(
+    """|package main
+       |func Niam(args map[string]interface{}) map[string]interface{} {
+       | return args
+       |}
+    """.stripMargin,
+    main = "niam"
+  )
+
+  override val testLargeInput = TestConfig(
+    """|package main
+       |func Main(args map[string]interface{}) map[string]interface{} {
+       | return args
+       |}
+    """.stripMargin)
+}
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/ActionLoopGo12ContainerTests.scala
similarity index 95%
copy from tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala
copy to tests/src/test/scala/runtime/actionContainers/ActionLoopGo12ContainerTests.scala
index 4c1bad7..aeda4cc 100644
--- a/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/ActionLoopGo12ContainerTests.scala
@@ -18,8 +18,8 @@
 package runtime.actionContainers
 
 //import java.util.concurrent.TimeoutException
-import actionContainers.{ActionContainer, ActionProxyContainerTestUtils}
 import actionContainers.ActionContainer.withContainer
+import actionContainers.{ActionContainer, ActionProxyContainerTestUtils}
 import common.WskActorSystem
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
@@ -29,13 +29,13 @@ import org.scalatest.junit.JUnitRunner
 import spray.json.{JsObject, JsString}
 
 @RunWith(classOf[JUnitRunner])
-class ActionLoopGoContainerTests
+class ActionLoopGo12ContainerTests
     extends ActionProxyContainerTestUtils
     with WskActorSystem {
 
   import GoResourceHelpers._
 
-  val goCompiler = "actionloop-golang-v1.11"
+  val goCompiler = "actionloop-golang-v1.12"
   val image = goCompiler
 
   def withActionLoopContainer(code: ActionContainer => Unit) =
@@ -62,14 +62,14 @@ class ActionLoopGoContainerTests
         |""".stripMargin
   }
 
-  private def helloSrc(main: String) = Seq(
+   def helloSrc(main: String) = Seq(
     Seq(s"${main}.go") -> helloGo(main)
   )
 
-  private def helloMsg(name: String = "Demo") =
+  def helloMsg(name: String = "Demo") =
     runPayload(JsObject("name" -> JsString(name)))
 
-  private def okMsg(key: String, value: String) =
+  def okMsg(key: String, value: String) =
     200 -> Some(JsObject(key -> JsString(value)))
 
   it should "run sample with init that does nothing" in {
diff --git a/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala b/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala
index 4c1bad7..84f6dd4 100644
--- a/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala
+++ b/tests/src/test/scala/runtime/actionContainers/ActionLoopGoContainerTests.scala
@@ -62,14 +62,14 @@ class ActionLoopGoContainerTests
         |""".stripMargin
   }
 
-  private def helloSrc(main: String) = Seq(
+   def helloSrc(main: String) = Seq(
     Seq(s"${main}.go") -> helloGo(main)
   )
 
-  private def helloMsg(name: String = "Demo") =
+  def helloMsg(name: String = "Demo") =
     runPayload(JsObject("name" -> JsString(name)))
 
-  private def okMsg(key: String, value: String) =
+  def okMsg(key: String, value: String) =
     200 -> Some(JsObject(key -> JsString(value)))
 
   it should "run sample with init that does nothing" in {
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index 450540d..3952414 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -40,8 +40,6 @@ echo "vcap.services.file=" >> whisk.properties
 
 # Build/Compile go
 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
+# just build docker images - they compile the proxy
 TERM=dumb ./gradlew distDocker
 
diff --git a/tools/travis/setup.sh b/tools/travis/setup.sh
index 7a17bff..18b5049 100755
--- a/tools/travis/setup.sh
+++ b/tools/travis/setup.sh
@@ -38,3 +38,5 @@ git clone https://github.com/apache/incubator-openwhisk-utilities.git
 git clone --depth=1 https://github.com/apache/incubator-openwhisk.git openwhisk
 cd openwhisk
 ./tools/travis/setup.sh
+go get github.com/sirupsen/logrus
+go get github.com/stretchr/testify/assert
diff --git a/tools/travis/test.sh b/tools/travis/test.sh
index d11e175..ae7876a 100755
--- a/tools/travis/test.sh
+++ b/tools/travis/test.sh
@@ -26,7 +26,8 @@ WHISKDIR="$ROOTDIR/../openwhisk"
 
 export OPENWHISK_HOME=$WHISKDIR
 cd ${ROOTDIR}
-TERM=dumb ./gradlew :tests:test
+pushd openwhisk
 go version
+go test -v
+popd
 TERM=dumb ./gradlew test --info
-