Skip to content

Commit

Permalink
Fix for Java actions and UTF8.
Browse files Browse the repository at this point in the history
  • Loading branch information
rabbah authored and sjfink committed Jan 25, 2017
1 parent 62aad24 commit 77a2bcd
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 21 deletions.
5 changes: 5 additions & 0 deletions core/javaAction/Dockerfile
Expand Up @@ -2,6 +2,11 @@ FROM buildpack-deps:trusty-curl

ENV DEBIAN_FRONTEND noninteractive

RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

ENV VERSION 8
ENV UPDATE 77
ENV BUILD 03
Expand Down
Expand Up @@ -52,9 +52,10 @@ public void start() {
}

private static void writeResponse(HttpExchange t, int code, String content) throws IOException {
t.sendResponseHeaders(code, content.length());
byte[] bytes = content.getBytes("UTF-8");
t.sendResponseHeaders(code, bytes.length);
OutputStream os = t.getResponseBody();
os.write(content.getBytes());
os.write(bytes);
os.close();
}

Expand Down
Binary file added tests/dat/actions/unicode.jar
Binary file not shown.
11 changes: 11 additions & 0 deletions tests/dat/actions/unicode/build.gradle
@@ -0,0 +1,11 @@
apply plugin: 'java'

version = '1.0'

repositories {
mavenCentral()
}

dependencies {
compile 'com.google.code.gson:gson:2.6.2'
}
28 changes: 28 additions & 0 deletions tests/dat/actions/unicode/src/main/java/Unicode.java
@@ -0,0 +1,28 @@
/*
* Copyright 2015-2016 IBM Corporation
*
* Licensed 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.
*/

import com.google.gson.JsonObject;

public class Unicode {
public static JsonObject main(JsonObject args) throws InterruptedException {
String delimiter = args.getAsJsonPrimitive("delimiter").getAsString();
JsonObject response = new JsonObject();
String str = delimiter + " ☃ " + delimiter;
System.out.println(str);
response.addProperty("winter", str);
return response;
}
}
29 changes: 29 additions & 0 deletions tests/src/actionContainers/JavaActionContainerTests.scala
Expand Up @@ -120,6 +120,35 @@ class JavaActionContainerTests extends FlatSpec with Matchers with WskActorSyste
err.trim shouldBe empty
}

it should "handle unicode in source, input params, logs, and result" in {
val (out, err) = withJavaContainer { c =>
val jar = JarBuilder.mkBase64Jar(
Seq("example", "HelloWhisk.java") -> """
| package example;
|
| import com.google.gson.JsonObject;
|
| public class HelloWhisk {
| public static JsonObject main(JsonObject args) {
| String delimiter = args.getAsJsonPrimitive("delimiter").getAsString();
| JsonObject response = new JsonObject();
| String str = delimiter + " ☃ " + delimiter;
| System.out.println(str);
| response.addProperty("winter", str);
| return response;
| }
| }
""".stripMargin)

val (initCode, _) = c.init(initPayload("example.HelloWhisk", jar))
val (runCode, runRes) = c.run(runPayload(JsObject("delimiter" -> JsString(""))))
runRes.get.fields.get("winter") shouldBe Some(JsString("❄ ☃ ❄"))
}

out should include("❄ ☃ ❄")
err.trim shouldBe empty
}

it should "fail to initialize with bad code" in {
val (out, err) = withJavaContainer { c =>
// This is valid zip file containing a single file, but not a valid
Expand Down
19 changes: 0 additions & 19 deletions tests/src/system/basic/WskBasicNodeTests.scala
Expand Up @@ -147,25 +147,6 @@ class WskBasicNodeTests
}
}

it should "Ensure that UTF-8 in supported in source files, input params, logs, and output results" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
val name = "unicodeGalore"

assetHelper.withCleaner(wsk.action, name) {
(action, _) =>
action.create(name, Some(TestUtils.getTestActionFilename("unicode.js")))
}

withActivation(wsk.activation, wsk.action.invoke(name, parameters = Map("delimiter" -> JsString("")))) {
activation =>
val response = activation.response
response.result.get.fields.get("error") shouldBe empty
response.result.get.fields.get("winter") should be(Some(JsString("❄ ☃ ❄")))

activation.logs.toList.flatten.mkString(" ") should include("❄ ☃ ❄")
}
}

// TODO: remove this tests and its assets when "whisk.js" is removed entirely as it is no longer necessary
it should "Ensure that whisk.invoke() returns a promise" in withAssetCleaner(wskprops) {
val expectedDuration = 3.seconds
Expand Down
60 changes: 60 additions & 0 deletions tests/src/system/basic/WskUnicodeTests.scala
@@ -0,0 +1,60 @@
/*
* Copyright 2015-2016 IBM Corporation
*
* Licensed 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 system.basic

import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

import common.JsHelpers
import common.TestHelpers
import common.TestUtils
import common.Wsk
import common.WskProps
import common.WskTestHelpers
import spray.json._

@RunWith(classOf[JUnitRunner])
class WskUnicodeTests
extends TestHelpers
with WskTestHelpers
with JsHelpers {

implicit val wskprops = WskProps()
val wsk = new Wsk

Map("node" -> "unicode.js", "java" -> "unicode.jar").foreach {
case (k, file) =>
s"$k action" should "Ensure that UTF-8 in supported in source files, input params, logs, and output results" in withAssetCleaner(wskprops) {
(wp, assetHelper) =>
val name = s"unicodeGalore.$k"

assetHelper.withCleaner(wsk.action, name) {
(action, _) =>
action.create(name, Some(TestUtils.getTestActionFilename(file)), main = if (k == "java") Some("Unicode") else None)
}

withActivation(wsk.activation, wsk.action.invoke(name, parameters = Map("delimiter" -> JsString("")))) {
activation =>
val response = activation.response
response.result.get.fields.get("error") shouldBe empty
response.result.get.fields.get("winter") should be(Some(JsString("❄ ☃ ❄")))

activation.logs.toList.flatten.mkString(" ") should include("❄ ☃ ❄")
}
}
}
}

0 comments on commit 77a2bcd

Please sign in to comment.