You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by da...@apache.org on 2017/08/23 01:37:28 UTC

[incubator-openwhisk-wskdeploy] branch master updated: Adding unit test cases for manifest_parser.go and more helloworld test cases (#368)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new c4d2d72  Adding unit test cases for manifest_parser.go and more helloworld test cases (#368)
c4d2d72 is described below

commit c4d2d72130882115f14dba74a299f8b31256639a
Author: Priti Desai <pd...@us.ibm.com>
AuthorDate: Tue Aug 22 18:37:26 2017 -0700

    Adding unit test cases for manifest_parser.go and more helloworld test cases (#368)
    
    * Adding unit tests for manifest parser
    * Adding more test cases of helloworld case
---
 parsers/manifest_parser_test.go               | 889 ++++++++++++++++++++++++++
 tests/usecases/helloworld/actions/Hello.java  |  29 +
 tests/usecases/helloworld/actions/hello.jar   | Bin 0 -> 966 bytes
 tests/usecases/helloworld/actions/hello.js    |  23 +
 tests/usecases/helloworld/actions/hello.py    |  23 +
 tests/usecases/helloworld/actions/hello.swift |  25 +
 6 files changed, 989 insertions(+)

diff --git a/parsers/manifest_parser_test.go b/parsers/manifest_parser_test.go
new file mode 100644
index 0000000..754714e
--- /dev/null
+++ b/parsers/manifest_parser_test.go
@@ -0,0 +1,889 @@
+// +build unit
+
+/*
+ * 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 parsers
+
+import (
+    "github.com/apache/incubator-openwhisk-wskdeploy/utils"
+    "github.com/stretchr/testify/assert"
+    "testing"
+    "strconv"
+    "fmt"
+    "os"
+    "io/ioutil"
+    "path/filepath"
+    "reflect"
+)
+
+// Test 1: validate manifest_parser:Unmarshal() method with a sample manifest in NodeJS
+// validate that manifest_parser is able to read and parse the manifest data
+func TestUnmarshalForHelloNodeJS(t *testing.T) {
+    data := `
+package:
+  name: helloworld
+  actions:
+    helloNodejs:
+      function: actions/hello.js
+      runtime: nodejs:6`
+    // set the zero value of struct ManifestYAML
+    m := ManifestYAML{}
+    // Unmarshal reads/parses manifest data and sets the values of ManifestYAML
+    // And returns an error if parsing a manifest data fails
+    err := NewYAMLParser().Unmarshal([]byte(data), &m)
+    if err == nil {
+        // ManifestYAML.Filepath does not get set by Parsers.Unmarshal
+        // as it takes manifest YAML data as a function parameter
+        // instead of file name of a manifest file, therefore there is
+        // no way for Unmarshal function to set ManifestYAML.Filepath field
+        // (TODO) Ideally we should change this functionality so that
+        // (TODO) filepath is set to the actual path of the manifest file
+        expectedResult := ""
+        actualResult := m.Filepath
+        assert.Equal(t, expectedResult, actualResult, "Expected filepath to be an empty"+
+            " string instead its set to "+actualResult+" which is invalid value")
+        // package name should be "helloworld"
+        expectedResult = "helloworld"
+        actualResult = m.Package.Packagename
+        assert.Equal(t, expectedResult, actualResult, "Expected package name "+expectedResult+" but got "+actualResult)
+        // manifest should contain only one action
+        expectedResult = string(1)
+        actualResult = string(len(m.Package.Actions))
+        assert.Equal(t, expectedResult, actualResult, "Expected 1 but got "+actualResult)
+        // get the action payload from the map of actions which is stored in
+        // ManifestYAML.Package.Actions with the type of map[string]Action
+        actionName := "helloNodejs"
+        if action, ok := m.Package.Actions[actionName]; ok {
+            // location/function of an action should be "actions/hello.js"
+            expectedResult = "actions/hello.js"
+            actualResult = action.Function
+            assert.Equal(t, expectedResult, actualResult, "Expected action function " + expectedResult + " but got " + actualResult)
+            // runtime of an action should be "nodejs:6"
+            expectedResult = "nodejs:6"
+            actualResult = action.Runtime
+            assert.Equal(t, expectedResult, actualResult, "Expected action runtime " + expectedResult + " but got " + actualResult)
+        } else {
+            t.Error("Action named "+actionName+" does not exist.")
+        }
+    }
+}
+
+// Test 2: validate manifest_parser:Unmarshal() method with a sample manifest in Java
+// validate that manifest_parser is able to read and parse the manifest data
+func TestUnmarshalForHelloJava (t *testing.T){
+    data := `
+package:
+  name: helloworld
+  actions:
+    helloJava:
+      function: actions/hello.jar
+      runtime: java
+      main: Hello`
+    m := ManifestYAML{}
+    err := NewYAMLParser().Unmarshal([]byte(data), &m)
+    // nothing to test if Unmarshal returns an err
+    if err == nil {
+        // get an action from map of actions where key is action name and
+        // value is Action struct
+        actionName := "helloJava"
+        if action, ok := m.Package.Actions[actionName]; ok {
+            // runtime of an action should be java
+            expectedResult := "java"
+            actualResult := action.Runtime
+            assert.Equal(t, expectedResult, actualResult, "Expected action runtime "+expectedResult+" but got "+actualResult)
+            // Main field should be set to "Hello"
+            expectedResult = action.Main
+            actualResult = "Hello"
+            assert.Equal(t, expectedResult, actualResult, "Expected action main function "+expectedResult+" but got "+actualResult)
+        } else {
+            t.Error("Expected action named "+actionName+" but does not exist.")
+        }
+    }
+}
+
+// Test 3: validate manifest_parser:Unmarshal() method with a sample manifest in Python
+// validate that manifest_parser is able to read and parse the manifest data
+func TestUnmarshalForHelloPython (t *testing.T){
+    data := `
+package:
+  name: helloworld
+  actions:
+    helloPython:
+      function: actions/hello.py
+      runtime: python`
+    m := ManifestYAML{}
+    err := NewYAMLParser().Unmarshal([]byte(data), &m)
+    // nothing to test if Unmarshal returns an err
+    if err == nil {
+        // get an action from map of actions which is defined as map[string]Action{}
+        actionName := "helloPython"
+        if action, ok := m.Package.Actions[actionName]; ok {
+            // runtime of an action should be python
+            expectedResult := "python"
+            actualResult := action.Runtime
+            assert.Equal(t, expectedResult, actualResult, "Expected action runtime "+expectedResult+" but got "+actualResult)
+        } else {
+            t.Error("Expected action named "+actionName+" but does not exist.")
+        }
+    }
+}
+
+// Test 4: validate manifest_parser:Unmarshal() method with a sample manifest in Swift
+// validate that manifest_parser is able to read and parse the manifest data
+func TestUnmarshalForHelloSwift (t *testing.T){
+    data := `
+package:
+  name: helloworld
+  actions:
+    helloSwift:
+      function: actions/hello.swift
+      runtime: swift`
+    m := ManifestYAML{}
+    err := NewYAMLParser().Unmarshal([]byte(data), &m)
+    // nothing to test if Unmarshal returns an err
+    if err == nil {
+        // get an action from map of actions which is defined as map[string]Action{}
+        actionName := "helloSwift"
+        if action, ok := m.Package.Actions[actionName]; ok {
+            // runtime of an action should be swift
+            expectedResult := "swift"
+            actualResult := action.Runtime
+            assert.Equal(t, expectedResult, actualResult, "Expected action runtime "+expectedResult+" but got "+actualResult)
+        } else {
+            t.Error("Expected action named "+actionName+" but does not exist.")
+        }
+    }
+}
+
+// Test 5: validate manifest_parser:Unmarshal() method for an action with parameters
+// validate that manifest_parser is able to read and parse the manifest data, specially
+// validate two input parameters and their values
+func TestUnmarshalForHelloWithParams(t *testing.T) {
+    var data = `
+package:
+   name: helloworld
+   actions:
+     helloWithParams:
+       function: actions/hello-with-params.js
+       runtime: nodejs:6
+       inputs:
+         name: Amy
+         place: Paris`
+    m := ManifestYAML{}
+    err := NewYAMLParser().Unmarshal([]byte(data), &m)
+    if err == nil {
+        actionName := "helloWithParams"
+        if action, ok := m.Package.Actions[actionName]; ok {
+            expectedResult := "Amy"
+            actualResult := action.Inputs["name"].Value.(string)
+            assert.Equal(t, expectedResult, actualResult,
+                "Expected input parameter "+expectedResult+" but got "+actualResult+"for name")
+            expectedResult = "Paris"
+            actualResult = action.Inputs["place"].Value.(string)
+            assert.Equal(t, expectedResult, actualResult,
+                "Expected input parameter "+expectedResult+" but got "+actualResult+"for place")
+        }
+    }
+}
+
+// Test 6: validate manifest_parser:Unmarshal() method for an invalid manifest
+// manifest_parser should report an error when a package section is missing
+func TestUnmarshalForMissingPackage(t *testing.T) {
+    data := `
+  actions:
+    helloNodejs:
+      function: actions/hello.js
+      runtime: nodejs:6
+    helloJava:
+      function: actions/hello.java`
+    // set the zero value of struct ManifestYAML
+    m := ManifestYAML{}
+    // Unmarshal reads/parses manifest data and sets the values of ManifestYAML
+    // And returns an error if parsing a manifest data fails
+    err := NewYAMLParser().Unmarshal([]byte(data), &m)
+    fmt.Println("Error: ", err)
+    fmt.Println("Filepath: \"",m.Filepath,"\"")
+    fmt.Println("Package: ", m.Package)
+    fmt.Println("PackageName: \"", m.Package.Packagename, "\"")
+    fmt.Println("Number of Actions: ", len(m.Package.Actions))
+    fmt.Println("Actions: ", m.Package.Actions)
+    // (TODO) Unmarshal does not report any error even if manifest file is missing required section.
+    // (TODO) In this test case, "Package" section is missing which is not reported,
+    // (TODO) instead ManifestYAML is set to its zero values
+    // assert.NotNil(t, err, "Expected some error from Unmarshal but got no error")
+}
+
+/*
+ Test 7: validate manifest_parser:ParseManifest() method for multiline parameters
+ manifest_parser should be able to parse all different mutliline combinations of
+ inputs section including:
+
+ case 1: value only
+ param:
+    value: <value>
+ case 2: type only
+ param:
+    type: <type>
+ case 3: type and value only
+ param:
+    type: <type>
+    value: <value>
+ case 4: default value
+ param:
+    type: <type>
+    default: <default value>
+*/
+func TestParseManifestForMultiLineParams(t *testing.T) {
+    // manifest file is located under ../tests folder
+    manifestFile := "../tests/dat/manifest_validate_multiline_params.yaml"
+    // read and parse manifest.yaml file
+    m := NewYAMLParser().ParseManifest(manifestFile)
+
+    // validate package name should be "validate"
+    expectedPackageName := m.Package.Packagename
+    actualPackageName := "validate"
+    assert.Equal(t, expectedPackageName, actualPackageName,
+        "Expected "+expectedPackageName+" but got "+actualPackageName)
+
+    // validate this package contains one action
+    expectedActionsCount := 1
+    actualActionsCount := len(m.Package.Actions)
+    assert.Equal(t, expectedActionsCount, actualActionsCount,
+        "Expected "+string(expectedActionsCount)+" but got "+string(actualActionsCount))
+
+    // here Package.Actions holds a map of map[string]Action
+    // where string is the action name so in case you create two actions with
+    // same name, will go unnoticed
+    // also, the Action struct does not have name field set it to action name
+    actionName := "validate_multiline_params"
+    if action, ok := m.Package.Actions[actionName]; ok {
+        // validate location/function of an action to be "actions/dump_params.js"
+        expectedResult := "actions/dump_params.js"
+        actualResult := action.Function
+        assert.Equal(t, expectedResult, actualResult, "Expected action function " + expectedResult + " but got " + actualResult)
+
+        // validate runtime of an action to be "nodejs:6"
+        expectedResult = "nodejs:6"
+        actualResult = action.Runtime
+        assert.Equal(t, expectedResult, actualResult, "Expected action runtime " + expectedResult + " but got " + actualResult)
+
+        // validate the number of inputs to this action
+        expectedResult = strconv.FormatInt(10, 10)
+        actualResult = strconv.FormatInt(int64(len(action.Inputs)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+
+        // validate inputs to this action
+        for input, param := range action.Inputs {
+            switch input {
+            case "param_string_value_only":
+                expectedResult = "foo"
+                actualResult = param.Value.(string)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_int_value_only":
+                expectedResult = strconv.FormatInt(123, 10)
+                actualResult = strconv.FormatInt(int64(param.Value.(int)), 10)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_float_value_only":
+                expectedResult = strconv.FormatFloat(3.14, 'f', -1, 64)
+                actualResult = strconv.FormatFloat(param.Value.(float64), 'f', -1, 64)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_string_type_and_value_only":
+                expectedResult = "foo"
+                actualResult = param.Value.(string)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+                expectedResult = "string"
+                actualResult = param.Type
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_string_type_only":
+                expectedResult = "string"
+                actualResult = param.Type
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_integer_type_only":
+                expectedResult = "integer"
+                actualResult = param.Type
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_float_type_only":
+                expectedResult = "float"
+                actualResult = param.Type
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_string_with_default":
+                expectedResult = "string"
+                actualResult = param.Type
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+                expectedResult = "bar"
+                actualResult = param.Default.(string)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_integer_with_default":
+                expectedResult = "integer"
+                actualResult = param.Type
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+                expectedResult = strconv.FormatInt(-1, 10)
+                actualResult = strconv.FormatInt(int64(param.Default.(int)), 10)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_float_with_default":
+                expectedResult = "float"
+                actualResult = param.Type
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+                expectedResult = strconv.FormatFloat(2.9, 'f', -1, 64)
+                actualResult = strconv.FormatFloat(param.Default.(float64), 'f', -1, 64)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            }
+        }
+
+        // validate outputs
+        // output payload is of type string and has a description
+        if payload, ok := action.Outputs["payload"]; ok {
+            p := payload.(map[interface{}]interface{})
+            expectedResult = "string"
+            actualResult = p["type"].(string)
+            assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            expectedResult = "parameter dump"
+            actualResult = p["description"].(string)
+            assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+        }
+    }
+}
+
+// Test 8: validate manifest_parser:ParseManifest() method for single line parameters
+// manifest_parser should be able to parse input section with different types of values
+func TestParseManifestForSingleLineParams(t *testing.T) {
+    // manifest file is located under ../tests folder
+    manifestFile := "../tests/dat/manifest_validate_singleline_params.yaml"
+    // read and parse manifest.yaml file
+    m := NewYAMLParser().ParseManifest(manifestFile)
+
+    // validate package name should be "validate"
+    expectedPackageName := m.Package.Packagename
+    actualPackageName := "validate"
+    assert.Equal(t, expectedPackageName, actualPackageName,
+        "Expected "+expectedPackageName+" but got "+actualPackageName)
+
+    // validate this package contains one action
+    expectedActionsCount := 1
+    actualActionsCount := len(m.Package.Actions)
+    assert.Equal(t, expectedActionsCount, actualActionsCount,
+        "Expected "+string(expectedActionsCount)+" but got "+string(actualActionsCount))
+
+    actionName := "validate_singleline_params"
+    if action, ok := m.Package.Actions[actionName]; ok {
+        // validate location/function of an action to be "actions/dump_params.js"
+        expectedResult := "actions/dump_params.js"
+        actualResult := action.Function
+        assert.Equal(t, expectedResult, actualResult, "Expected action function " + expectedResult + " but got " + actualResult)
+
+        // validate runtime of an action to be "nodejs:6"
+        expectedResult = "nodejs:6"
+        actualResult = action.Runtime
+        assert.Equal(t, expectedResult, actualResult, "Expected action runtime " + expectedResult + " but got " + actualResult)
+
+        // validate the number of inputs to this action
+        expectedResult = strconv.FormatInt(17, 10)
+        actualResult = strconv.FormatInt(int64(len(action.Inputs)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+
+        // validate inputs to this action
+        for input, param := range action.Inputs {
+            switch input {
+            case "param_simple_string":
+                expectedResult = "foo"
+                actualResult = param.Value.(string)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_integer_1":
+                expectedResult = strconv.FormatInt(1, 10)
+                actualResult = strconv.FormatInt(int64(param.Value.(int)), 10)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_integer_2":
+                expectedResult = strconv.FormatInt(0, 10)
+                actualResult = strconv.FormatInt(int64(param.Value.(int)), 10)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_integer_3":
+                expectedResult = strconv.FormatInt(-1, 10)
+                actualResult = strconv.FormatInt(int64(param.Value.(int)), 10)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_integer_4":
+                expectedResult = strconv.FormatInt(99999, 10)
+                actualResult = strconv.FormatInt(int64(param.Value.(int)), 10)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_integer_5":
+                expectedResult = strconv.FormatInt(-99999, 10)
+                actualResult = strconv.FormatInt(int64(param.Value.(int)), 10)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_float_1":
+                expectedResult = strconv.FormatFloat(1.1, 'f', -1, 64)
+                actualResult = strconv.FormatFloat(param.Value.(float64), 'f', -1, 64)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_float_2":
+                expectedResult = strconv.FormatFloat(0.0, 'f', -1, 64)
+                actualResult = strconv.FormatFloat(param.Value.(float64), 'f', -1, 64)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_float_3":
+                expectedResult = strconv.FormatFloat(-1.1, 'f', -1, 64)
+                actualResult = strconv.FormatFloat(param.Value.(float64), 'f', -1, 64)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_env_var_1":
+                expectedResult = "$GOPATH"
+                actualResult = param.Value.(string)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_invalid_env_var":
+                expectedResult = "$DollarSignNotInEnv"
+                actualResult = param.Value.(string)
+                assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            case "param_simple_implied_empty":
+                assert.Nil(t, param.Value, "Expected nil")
+            case "param_simple_explicit_empty_1":
+                actualResult = param.Value.(string)
+                assert.Empty(t, actualResult, "Expected empty string but got "+actualResult)
+            case "param_simple_explicit_empty_2":
+                actualResult = param.Value.(string)
+                assert.Empty(t, actualResult, "Expected empty string but got "+actualResult)
+            }
+        }
+
+        // validate outputs
+        // output payload is of type string and has a description
+        if payload, ok := action.Outputs["payload"]; ok {
+            p := payload.(map[interface{}]interface{})
+            expectedResult = "string"
+            actualResult = p["type"].(string)
+            assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+            expectedResult = "parameter dump"
+            actualResult = p["description"].(string)
+            assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+        }
+    }
+}
+
+// Test 9: validate manifest_parser.ComposeActions() method for implicit runtimes
+// when a runtime of an action is not provided, manifest_parser determines the runtime
+// based on the file extension of an action file
+func TestComposeActionsForImplicitRuntimes (t *testing.T) {
+    data :=
+`package:
+  name: helloworld
+  actions:
+    helloNodejs:
+      function: ../tests/usecases/helloworld/actions/hello.js
+    helloJava:
+      function: ../tests/usecases/helloworld/actions/hello.jar
+      main: Hello
+    helloPython:
+      function: ../tests/usecases/helloworld/actions/hello.py
+    helloSwift:
+      function: ../tests/usecases/helloworld/actions/hello.swift`
+
+    dir, _ := os.Getwd()
+    tmpfile, err := ioutil.TempFile(dir, "manifest_parser_validate_runtimes_")
+    if err == nil {
+        defer os.Remove(tmpfile.Name()) // clean up
+        if _, err := tmpfile.Write([]byte(data)); err == nil {
+            // read and parse manifest.yaml file
+            p := NewYAMLParser()
+            m := p.ParseManifest(tmpfile.Name())
+            actions, _, err := p.ComposeActions(m, tmpfile.Name())
+            var expectedResult string
+            if err == nil {
+                for i:=0; i<len(actions); i++ {
+                    if actions[i].Action.Name == "helloNodejs" {
+                        expectedResult = "nodejs:default"
+                        // (TODO) change expectedResult in the following condition
+                        // (TODO) once issue #306 is fixed as runtime is set to
+                        // (TODO) nodejs:default for any kind of action file except
+                        // (TODO) files with extension .js, .py, and .swift
+                    } else if actions[i].Action.Name == "helloJava" {
+                        expectedResult = "nodejs:default"
+                    } else if actions[i].Action.Name == "helloPython" {
+                        expectedResult = "python"
+                    } else if actions[i].Action.Name == "helloSwift" {
+                        expectedResult = "swift:default"
+                    }
+                    actualResult := actions[i].Action.Exec.Kind
+                    assert.Equal(t, expectedResult, actualResult, "Expected "+expectedResult+" but got "+actualResult)
+                }
+            }
+
+        }
+        tmpfile.Close()
+    }
+}
+
+// Test 10: validate manifest_parser.ComposeActions() method for invalid runtimes
+// when a runtime of an action is set to some garbage, manifest_parser should
+// report an error for that action
+func TestComposeActionsForInvalidRuntime (t *testing.T) {
+    data :=
+`package:
+   name: helloworld
+   actions:
+     helloInvalidRuntime:
+       function: ../tests/usecases/helloworld/actions/hello.js
+       runtime: invalid`
+    dir, _ := os.Getwd()
+    tmpfile, err := ioutil.TempFile(dir, "manifest_parser_validate_runtime_")
+    if err == nil {
+        defer os.Remove(tmpfile.Name()) // clean up
+        if _, err := tmpfile.Write([]byte(data)); err == nil {
+            // read and parse manifest.yaml file
+            p := NewYAMLParser()
+            m := p.ParseManifest(tmpfile.Name())
+            _, _, err := p.ComposeActions(m, tmpfile.Name())
+            // (TODO) uncomment the following test case after issue #307 is fixed
+            // (TODO) its failing right now as we are lacking check on invalid runtime
+            // assert.NotNil(t, err, "Invalid runtime, ComposeActions should report an error")
+            // (TODO) remove this print statement after uncommenting above test case
+            fmt.Println(err)
+        }
+        tmpfile.Close()
+    }
+}
+
+// Test 11: validate manfiest_parser.ComposeActions() method for single line parameters
+// manifest_parser should be able to parse input section with different types of values
+func TestComposeActionsForSingleLineParams (t *testing.T) {
+    // manifest file is located under ../tests folder
+    manifestFile := "../tests/dat/manifest_validate_singleline_params.yaml"
+    // read and parse manifest.yaml file
+    p := NewYAMLParser()
+    m := p.ParseManifest(manifestFile)
+    actions, _, err := p.ComposeActions(m, manifestFile)
+
+    if err == nil {
+        // assert that the actions variable has only one action
+        assert.Equal(t, 1, len(actions), "We have defined only one action but we got " + string(len(actions)))
+
+        action := actions[0]
+
+        // param_simple_string should value "foo"
+        expectedResult := "foo"
+        actualResult := action.Action.Parameters.GetValue("param_simple_string").(string)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_integer_1 should have value 1
+        expectedResult = strconv.FormatInt(1, 10)
+        actualResult = strconv.FormatInt(int64(action.Action.Parameters.GetValue("param_simple_integer_1").(int)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_integer_2 should have value 0
+        expectedResult = strconv.FormatInt(0, 10)
+        actualResult = strconv.FormatInt(int64(action.Action.Parameters.GetValue("param_simple_integer_2").(int)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_integer_3 should have value -1
+        expectedResult = strconv.FormatInt(-1, 10)
+        actualResult = strconv.FormatInt(int64(action.Action.Parameters.GetValue("param_simple_integer_3").(int)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_integer_4 should have value 99999
+        expectedResult = strconv.FormatInt(99999, 10)
+        actualResult = strconv.FormatInt(int64(action.Action.Parameters.GetValue("param_simple_integer_4").(int)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_integer_5 should have value -99999
+        expectedResult = strconv.FormatInt(-99999, 10)
+        actualResult = strconv.FormatInt(int64(action.Action.Parameters.GetValue("param_simple_integer_5").(int)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_float_1 should have value 1.1
+        expectedResult = strconv.FormatFloat(1.1, 'f', -1, 64)
+        actualResult = strconv.FormatFloat(action.Action.Parameters.GetValue("param_simple_float_1").(float64), 'f', -1, 64)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_float_2 should have value 0.0
+        expectedResult = strconv.FormatFloat(0.0, 'f', -1, 64)
+        actualResult = strconv.FormatFloat(action.Action.Parameters.GetValue("param_simple_float_2").(float64), 'f', -1, 64)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_float_3 should have value -1.1
+        expectedResult = strconv.FormatFloat(-1.1, 'f', -1, 64)
+        actualResult = strconv.FormatFloat(action.Action.Parameters.GetValue("param_simple_float_3").(float64), 'f', -1, 64)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_env_var_1 should have value of env. variable $GOPATH
+        expectedResult = os.Getenv("GOPATH")
+        actualResult = action.Action.Parameters.GetValue("param_simple_env_var_1").(string)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_invalid_env_var should have value of ""
+        expectedResult = ""
+        actualResult = action.Action.Parameters.GetValue("param_simple_invalid_env_var").(string)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_simple_implied_empty should be ""
+        actualResult = action.Action.Parameters.GetValue("param_simple_implied_empty").(string)
+        assert.Empty(t, actualResult, "Expected empty string but got "+actualResult)
+
+        // param_simple_explicit_empty_1 should be ""
+        actualResult = action.Action.Parameters.GetValue("param_simple_explicit_empty_1").(string)
+        assert.Empty(t, actualResult, "Expected empty string but got " + actualResult)
+
+        // param_simple_explicit_empty_2 should be ""
+        actualResult = action.Action.Parameters.GetValue("param_simple_explicit_empty_2").(string)
+        assert.Empty(t, actualResult, "Expected empty string but got " + actualResult)
+    }
+}
+
+
+// Test 12: validate manfiest_parser.ComposeActions() method for multi line parameters
+// manifest_parser should be able to parse input section with different types of values
+func TestComposeActionsForMultiLineParams (t *testing.T) {
+    // manifest file is located under ../tests folder
+    manifestFile := "../tests/dat/manifest_validate_multiline_params.yaml"
+    // read and parse manifest.yaml file
+    p := NewYAMLParser()
+    m := p.ParseManifest(manifestFile)
+    actions, _, err := p.ComposeActions(m, manifestFile)
+
+    if err == nil {
+        // assert that the actions variable has only one action
+        assert.Equal(t, 1, len(actions), "We have defined only one action but we got " + string(len(actions)))
+
+        action := actions[0]
+
+        fmt.Println(action.Action.Parameters)
+
+        // param_string_value_only should be "foo"
+        expectedResult := "foo"
+        actualResult := action.Action.Parameters.GetValue("param_string_value_only").(string)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_int_value_only should be 123
+        expectedResult = strconv.FormatInt(123, 10)
+        actualResult = strconv.FormatInt(int64(action.Action.Parameters.GetValue("param_int_value_only").(int)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_float_value_only should be 3.14
+        expectedResult = strconv.FormatFloat(3.14, 'f', -1, 64)
+        actualResult = strconv.FormatFloat(action.Action.Parameters.GetValue("param_float_value_only").(float64), 'f', -1, 64)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_string_type_and_value_only should be foo
+        expectedResult = "foo"
+        actualResult = action.Action.Parameters.GetValue("param_string_type_and_value_only").(string)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_string_type_only should be ""
+        actualResult = action.Action.Parameters.GetValue("param_string_type_only").(string)
+        assert.Empty(t, actualResult, "Expected empty string but got " + actualResult)
+
+        // param_integer_type_only should be 0
+        expectedResult = strconv.FormatInt(0, 10)
+        actualResult = strconv.FormatInt(int64(action.Action.Parameters.GetValue("param_integer_type_only").(int)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_float_type_only should be 0
+        expectedResult = strconv.FormatFloat(0.0, 'f', -1, 64)
+        actualResult = strconv.FormatFloat(action.Action.Parameters.GetValue("param_float_type_only").(float64), 'f', -1, 64)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_string_with_default should be "bar"
+        expectedResult = "bar"
+        actualResult = action.Action.Parameters.GetValue("param_string_with_default").(string)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_integer_with_default should be -1
+        expectedResult = strconv.FormatInt(-1, 10)
+        actualResult = strconv.FormatInt(int64(action.Action.Parameters.GetValue("param_integer_with_default").(int)), 10)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+
+        // param_float_with_default should be 2.9
+        expectedResult = strconv.FormatFloat(2.9, 'f', -1, 64)
+        actualResult = strconv.FormatFloat(action.Action.Parameters.GetValue("param_float_with_default").(float64), 'f', -1, 64)
+        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+    }
+}
+
+
+// Test 13: validate manfiest_parser.ComposeActions() method
+func TestComposeActionsForFunction (t *testing.T) {
+    data :=
+`package:
+  name: helloworld
+  actions:
+    hello1:
+      function: ../tests/usecases/helloworld/actions/hello.js`
+    // (TODO) uncomment this after we add support for action file content from URL
+    // hello2:
+    //  function: https://raw.githubusercontent.com/apache/incubator-openwhisk-wskdeploy/master/tests/usecases/helloworld/manifest.yaml`
+    dir, _ := os.Getwd()
+    tmpfile, err := ioutil.TempFile(dir, "manifest_parser_validate_locations_")
+    if err == nil {
+        defer os.Remove(tmpfile.Name()) // clean up
+        if _, err := tmpfile.Write([]byte(data)); err == nil {
+            // read and parse manifest.yaml file
+            p := NewYAMLParser()
+            m := p.ParseManifest(tmpfile.Name())
+            actions, _, err := p.ComposeActions(m, tmpfile.Name())
+            var expectedResult, actualResult string
+            if err == nil {
+                for i:=0; i<len(actions); i++ {
+                    if actions[i].Action.Name == "hello1" {
+                        expectedResult, _ = filepath.Abs("../tests/usecases/helloworld/actions/hello.js")
+                        actualResult, _ = filepath.Abs(actions[i].Filepath)
+                        assert.Equal(t, expectedResult, actualResult, "Expected " + expectedResult + " but got " + actualResult)
+                    // (TODO) Uncomment the following condition, hello2
+                    // (TODO) after issue # 311 is fixed
+                    //} else if actions[i].Action.Name == "hello2" {
+                    //  assert.NotNil(t, actions[i].Action.Exec.Code, "Expected source code from an action file but found it empty")
+                    }
+                }
+            }
+
+        }
+        tmpfile.Close()
+    }
+
+}
+
+// (TODO) uncomment this test case after issue # 312 is fixed
+// Test 14: validate manfiest_parser.ComposeActions() method
+//func TestComposeActionsForLimits (t *testing.T) {
+//  data :=
+//`package:
+//  name: helloworld
+//  actions:
+//    hello1:
+//      function: ../tests/usecases/helloworld/actions/hello.js
+//    hello2:
+//      function: ../tests/usecases/helloworld/actions/hello.js
+//      limits:
+//        timeout: 60
+//        memorySize: 128
+//        logSize: 1
+//        concurrentActivations: 10
+//        userInvocationRate: 50
+//        codeSize: 1024
+//        parameterSize: 128`
+//  dir, _ := os.Getwd()
+//  tmpfile, err := ioutil.TempFile(dir, "manifest_parser_validate_limits_")
+//  if err == nil {
+//      defer os.Remove(tmpfile.Name()) // clean up
+//      if _, err := tmpfile.Write([]byte(data)); err == nil {
+//          // read and parse manifest.yaml file
+//          p := NewYAMLParser()
+//          m := p.ParseManifest(tmpfile.Name())
+//          actions, _, err := p.ComposeActions(m, tmpfile.Name())
+//          //var expectedResult, actualResult string
+//          if err == nil {
+//              for i:=0; i<len(actions); i++ {
+//                  if actions[i].Action.Name == "hello1" {
+//                      fmt.Println(actions[i].Action.Limits)
+//                      //assert.Nil(t, actions[i].Action.Limits, "Expected limit section to be empty but got " + actions[i].Action.Limits)
+//                  } else if actions[i].Action.Name == "hello2" {
+//                      fmt.Println(actions[i].Action.Limits)
+//                      //assert.NotNil(t, actions[i].Action.Limits, "Expected limit section to be not empty but found it empty")
+//                  }
+//              }
+//          }
+//
+//      }
+//      tmpfile.Close()
+//  }
+//}
+
+// Test 15: validate manfiest_parser.ComposeActions() method
+func TestComposeActionsForWebActions (t *testing.T) {
+    data :=
+`package:
+  name: helloworld
+  actions:
+    hello:
+      function: ../tests/usecases/helloworld/actions/hello.js
+      annotations:
+        foo: bar
+      web-export: true`
+    // (TODO) remove annotations from manifest file after we fix issue # 313
+    dir, _ := os.Getwd()
+    tmpfile, err := ioutil.TempFile(dir, "manifest_parser_validate_web_actions_")
+    if err == nil {
+        defer os.Remove(tmpfile.Name()) // clean up
+        if _, err := tmpfile.Write([]byte(data)); err == nil {
+            // read and parse manifest.yaml file
+            p := NewYAMLParser()
+            m := p.ParseManifest(tmpfile.Name())
+            actions, _, err := p.ComposeActions(m, tmpfile.Name())
+            if err == nil {
+                for i:=0; i<len(actions); i++ {
+                    if actions[i].Action.Name == "hello" {
+                        for _, a := range actions[i].Action.Annotations {
+                            switch a.Key {
+                            case "web-export":
+                                assert.Equal(t, true, a.Value, "Expected true for web-export but got "+strconv.FormatBool(a.Value.(bool)))
+                            case "raw-http":
+                                assert.Equal(t, false, a.Value, "Expected false for raw-http but got "+strconv.FormatBool(a.Value.(bool)))
+                            case "final":
+                                assert.Equal(t, true, a.Value, "Expected true for final but got "+strconv.FormatBool(a.Value.(bool)))
+                            }
+                        }
+                    }
+                }
+            }
+
+        }
+        tmpfile.Close()
+    }
+}
+
+// Test 16: validate manifest_parser.ResolveParameter() method
+func TestResolveParameterForMultiLineParams (t *testing.T) {
+    p := "name"
+    v := "foo"
+    y := reflect.TypeOf(v).Name() // y := string
+    d := "default_name"
+
+    // type string - value only param
+    param1 := Parameter{Value: v, multiline: true}
+    r1, _ := ResolveParameter(p, &param1)
+    assert.Equal(t, v, r1, "Expected value "+v+" but got "+r1.(string))
+    assert.IsType(t, v, r1, "Expected parameter %v of type %T but found %T", p, v, r1)
+
+    // type string - type and value only param
+    param2 := Parameter{Type: y, Value: v, multiline: true}
+    r2, _ := ResolveParameter(p, &param2)
+    assert.Equal(t, v, r2, "Expected value "+v+" but got "+r2.(string))
+    assert.IsType(t, v, r2, "Expected parameter %v of type %T but found %T", p, v, r2)
+
+    // type string - type, no value, but default value param
+    param3 := Parameter{Type: y, Default: d, multiline: true}
+    r3, _ := ResolveParameter(p, &param3)
+    assert.Equal(t, d, r3, "Expected value "+d+" but got "+r3.(string))
+    assert.IsType(t, d, r3, "Expected parameter %v of type %T but found %T", p, d, r3)
+
+    // type string - type and value only param
+    // type is "string" and value is of type "int"
+    // ResolveParameter matches specified type with the type of the specified value
+    // it fails if both types don't match
+    // ResolveParameter determines type from the specified value
+    // in this case, ResolveParameter returns value of type int
+    v1 := 11
+    param4 := Parameter{Type: y, Value: v1, multiline: true}
+    r4, _ := ResolveParameter(p, &param4)
+    assert.Equal(t, v1, r4, "Expected value "+strconv.FormatInt(int64(v1), 10)+" but got "+strconv.FormatInt(int64(r4.(int)), 10))
+    assert.IsType(t, v1, r4, "Expected parameter %v of type %T but found %T", p, v1, r4)
+
+    // type invalid - type only param
+    param5 := Parameter{Type: "invalid", multiline: true}
+    _, err := ResolveParameter(p, &param5)
+    assert.NotNil(t, err, "Expected error saying Invalid type for parameter")
+    expectedErr := utils.NewParserErr("",-1, "Invalid Type for parameter. [invalid]")
+    assert.Equal(t, err, expectedErr, "Expected error "+expectedErr.Error()+" but found "+err.Error())
+
+    // type none - param without type, without value, and without default value
+    param6 := Parameter{multiline: true}
+    r6, _ := ResolveParameter("none", &param6)
+    assert.Empty(t, r6, "Expected default value of empty string but found "+r6.(string))
+
+}
diff --git a/tests/usecases/helloworld/actions/Hello.java b/tests/usecases/helloworld/actions/Hello.java
new file mode 100644
index 0000000..33b2396
--- /dev/null
+++ b/tests/usecases/helloworld/actions/Hello.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+import com.google.gson.JsonObject;
+public class Hello {
+    public static JsonObject main(JsonObject args) {
+        String name = "stranger";
+        if (args.has("name"))
+            name = args.getAsJsonPrimitive("name").getAsString();
+        JsonObject response = new JsonObject();
+        response.addProperty("greeting", "Hello " + name + "!");
+        return response;
+    }
+}
+
diff --git a/tests/usecases/helloworld/actions/hello.jar b/tests/usecases/helloworld/actions/hello.jar
new file mode 100644
index 0000000..b05753f
Binary files /dev/null and b/tests/usecases/helloworld/actions/hello.jar differ
diff --git a/tests/usecases/helloworld/actions/hello.js b/tests/usecases/helloworld/actions/hello.js
new file mode 100644
index 0000000..5486e7b
--- /dev/null
+++ b/tests/usecases/helloworld/actions/hello.js
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/*
+ * Return a simple greeting message for the whole world.
+ */
+function main(params) {
+    return {payload:  'Hello, world!'};
+}
diff --git a/tests/usecases/helloworld/actions/hello.py b/tests/usecases/helloworld/actions/hello.py
new file mode 100644
index 0000000..44c3bd1
--- /dev/null
+++ b/tests/usecases/helloworld/actions/hello.py
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+def main(args):
+    name = args.get("name", "stranger")
+    greeting = "Hello " + name + "!"
+    print(greeting)
+    return {"greeting": greeting}
+
diff --git a/tests/usecases/helloworld/actions/hello.swift b/tests/usecases/helloworld/actions/hello.swift
new file mode 100644
index 0000000..6bf7e23
--- /dev/null
+++ b/tests/usecases/helloworld/actions/hello.swift
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+func main(args: [String:Any]) -> [String:Any] {
+    if let name = args["name"] as? String {
+        return [ "greeting" : "Hello \(name)!" ]
+    } else {
+        return [ "greeting" : "Hello stranger!" ]
+    }
+}
+

-- 
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].