You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by cs...@apache.org on 2017/11/11 13:21:28 UTC
[incubator-openwhisk] branch master updated: Replace test cases of
api gateway with REST (#2944)
This is an automated email from the ASF dual-hosted git repository.
csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push:
new c5e12ce Replace test cases of api gateway with REST (#2944)
c5e12ce is described below
commit c5e12ce8b2ffdc10a4c418eb20c2dd0255bb5981
Author: Vincent <sh...@us.ibm.com>
AuthorDate: Sat Nov 11 08:21:26 2017 -0500
Replace test cases of api gateway with REST (#2944)
---
.../apigw/healthtests/ApiGwCliEndToEndTests.scala | 33 ++
.../apigw/healthtests/ApiGwEndToEndTests.scala | 73 ++-
.../apigw/healthtests/ApiGwRestEndToEndTests.scala | 93 +++
tests/src/test/scala/common/rest/WskRest.scala | 97 ++--
.../test/ApiGwCliRoutemgmtActionTests.scala | 28 +
.../test/ApiGwRestRoutemgmtActionTests.scala | 31 +
.../actions/test/ApiGwRoutemgmtActionTests.scala | 227 +-------
.../scala/whisk/core/cli/test/ApiGwCliTests.scala | 33 ++
.../scala/whisk/core/cli/test/ApiGwRestTests.scala | 248 ++++++++
.../scala/whisk/core/cli/test/ApiGwTests.scala | 641 +++++++--------------
.../scala/whisk/core/cli/test/BaseApiGwTests.scala | 165 ++++++
.../whisk/core/cli/test/WskCliApiGwTests.scala | 438 ++++++++++++++
12 files changed, 1407 insertions(+), 700 deletions(-)
diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwCliEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwCliEndToEndTests.scala
new file mode 100644
index 0000000..3025fab
--- /dev/null
+++ b/tests/src/test/scala/apigw/healthtests/ApiGwCliEndToEndTests.scala
@@ -0,0 +1,33 @@
+/*
+ * 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 apigw.healthtests
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import common.Wsk
+import common.TestUtils._
+
+/**
+ * Basic tests of the download link for Go CLI binaries
+ */
+@RunWith(classOf[JUnitRunner])
+class ApiGwCliEndToEndTests extends ApiGwEndToEndTests {
+ override lazy val wsk: common.Wsk = new Wsk
+ override val createCode: Int = SUCCESS_EXIT
+}
diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
index d0dbe92..8995c7a 100644
--- a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
+++ b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
@@ -34,7 +34,7 @@ import com.jayway.restassured.RestAssured
import common.TestHelpers
import common.TestUtils
import common.TestUtils._
-import common.Wsk
+import common.BaseWsk
import common.WskProps
import common.WskTestHelpers
import spray.json._
@@ -45,7 +45,7 @@ import system.rest.RestUtil
* Basic tests of the download link for Go CLI binaries
*/
@RunWith(classOf[JUnitRunner])
-class ApiGwEndToEndTests
+abstract class ApiGwEndToEndTests
extends FlatSpec
with Matchers
with RestUtil
@@ -53,23 +53,58 @@ class ApiGwEndToEndTests
with WskTestHelpers
with BeforeAndAfterAll {
- implicit val wskprops = WskProps()
- val wsk = new Wsk
- val clinamespace = wsk.namespace.whois()
+ implicit val wskprops: common.WskProps = WskProps()
+ val wsk: BaseWsk
+ val namespace: String = wsk.namespace.whois()
+ val createCode: Int
// Custom CLI properties file
- val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
+ val cliWskPropsFile: java.io.File = File.createTempFile("wskprops", ".tmp")
/*
* Create a CLI properties file for use by the tests
*/
- override def beforeAll() = {
+ override def beforeAll: Unit = {
cliWskPropsFile.deleteOnExit()
val wskprops = WskProps(token = "SOME TOKEN")
wskprops.writeFile(cliWskPropsFile)
println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}")
}
+ def verifyAPICreated(rr: RunResult): Unit = {
+ rr.stdout should include("ok: created API")
+ val apiurl = rr.stdout.split("\n")(1)
+ println(s"apiurl: '$apiurl'")
+ }
+
+ def verifyAPIList(rr: RunResult,
+ actionName: String,
+ testurlop: String,
+ testapiname: String,
+ testbasepath: String,
+ testrelpath: String): Unit = {
+ rr.stdout should include("ok: APIs")
+ rr.stdout should include regex (s"$actionName\\s+$testurlop\\s+$testapiname\\s+")
+ rr.stdout should include(testbasepath + testrelpath)
+ }
+
+ def verifyAPISwaggerCreated(rr: RunResult): Unit = {
+ rr.stdout should include("ok: created API")
+ }
+
+ def writeSwaggerFile(rr: RunResult): File = {
+ val swaggerfile = File.createTempFile("api", ".json")
+ swaggerfile.deleteOnExit()
+ val bw = new BufferedWriter(new FileWriter(swaggerfile))
+ bw.write(rr.stdout)
+ bw.close()
+ return swaggerfile
+ }
+
+ def getSwaggerApiUrl(rr: RunResult): String = {
+ return rr.stdout.split("\n")(1)
+ }
+
behavior of "Wsk api"
it should s"create an API and successfully invoke that API" in {
@@ -83,7 +118,7 @@ class ApiGwEndToEndTests
val urlqueryvalue = testName
try {
- println("cli namespace: " + clinamespace)
+ println("Namespace: " + namespace)
// Delete any lingering stale api from previous run that may not have been deleted properly
wsk.api.delete(
@@ -93,12 +128,14 @@ class ApiGwEndToEndTests
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo-web-http.js")
+ println("action creation Namespace: " + namespace)
wsk.action.create(
name = actionName,
artifact = Some(file),
- expectedExitCode = SUCCESS_EXIT,
+ expectedExitCode = createCode,
annotations = Map("web-export" -> true.toJson))
+ println("creation Namespace: " + namespace)
// Create the API
var rr = wsk.api.create(
basepath = Some(testbasepath),
@@ -108,9 +145,7 @@ class ApiGwEndToEndTests
apiname = Some(testapiname),
responsetype = Some("http"),
cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
- rr.stdout should include("ok: created API")
- val apiurl = rr.stdout.split("\n")(1)
- println(s"apiurl: '$apiurl'")
+ verifyAPICreated(rr)
// Validate the API was successfully created
// List result will look like:
@@ -122,17 +157,11 @@ class ApiGwEndToEndTests
relpath = Some(testrelpath),
operation = Some(testurlop),
cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"$actionName\\s+$testurlop\\s+$testapiname\\s+")
- rr.stdout should include(testbasepath + testrelpath)
+ verifyAPIList(rr, actionName, testurlop, testapiname, testbasepath, testrelpath)
// Recreate the API using a JSON swagger file
rr = wsk.api.get(basepathOrApiName = Some(testbasepath), cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
- val swaggerfile = File.createTempFile("api", ".json")
- swaggerfile.deleteOnExit()
- val bw = new BufferedWriter(new FileWriter(swaggerfile))
- bw.write(rr.stdout)
- bw.close()
+ val swaggerfile = writeSwaggerFile(rr)
// Delete API to that it can be recreated again using the generated swagger file
val deleteApiResult = wsk.api.delete(
@@ -143,8 +172,8 @@ class ApiGwEndToEndTests
// Create the API again, but use the swagger file this time
rr = wsk.api
.create(swagger = Some(swaggerfile.getAbsolutePath()), cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
- rr.stdout should include("ok: created API")
- val swaggerapiurl = rr.stdout.split("\n")(1)
+ verifyAPISwaggerCreated(rr)
+ val swaggerapiurl = getSwaggerApiUrl(rr)
println(s"Returned api url: '${swaggerapiurl}'")
// Call the API URL and validate the results
diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwRestEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwRestEndToEndTests.scala
new file mode 100644
index 0000000..279da3c
--- /dev/null
+++ b/tests/src/test/scala/apigw/healthtests/ApiGwRestEndToEndTests.scala
@@ -0,0 +1,93 @@
+/*
+ * 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 apigw.healthtests
+
+import java.io.BufferedWriter
+import java.io.File
+import java.io.FileWriter
+
+import akka.http.scaladsl.model.StatusCodes.OK
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import common.TestUtils._
+import common.rest.WskRest
+import common.rest.RestResult
+
+@RunWith(classOf[JUnitRunner])
+class ApiGwRestEndToEndTests extends ApiGwEndToEndTests {
+
+ override lazy val wsk: common.rest.WskRest = new WskRest
+ override val createCode: Int = OK.intValue
+
+ override def verifyAPICreated(rr: RunResult): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ apiResultRest.statusCode shouldBe OK
+ val apiurl = apiResultRest.getField("gwApiUrl") + "/path"
+ println(s"apiurl: '$apiurl'")
+ }
+
+ override def verifyAPIList(rr: RunResult,
+ actionName: String,
+ testurlop: String,
+ testapiname: String,
+ testbasepath: String,
+ testrelpath: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val apiValue = RestResult.getFieldJsObject(apiResultRest.getFieldListJsObject("apis")(0), "value")
+ val apidoc = RestResult.getFieldJsObject(apiValue, "apidoc")
+ val basepath = RestResult.getField(apidoc, "basePath")
+ basepath shouldBe testbasepath
+
+ val paths = RestResult.getFieldJsObject(apidoc, "paths")
+ paths.fields.contains(testrelpath) shouldBe true
+
+ val info = RestResult.getFieldJsObject(apidoc, "info")
+ val title = RestResult.getField(info, "title")
+ title shouldBe testapiname
+
+ val relpath = RestResult.getFieldJsObject(paths, testrelpath)
+ val urlop = RestResult.getFieldJsObject(relpath, testurlop)
+ val openwhisk = RestResult.getFieldJsObject(urlop, "x-openwhisk")
+ val actionN = RestResult.getField(openwhisk, "action")
+ actionN shouldBe actionName
+ }
+
+ override def verifyAPISwaggerCreated(rr: RunResult): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ apiResultRest.statusCode shouldBe OK
+ }
+
+ override def writeSwaggerFile(rr: RunResult): File = {
+ val swaggerfile = File.createTempFile("api", ".json")
+ swaggerfile.deleteOnExit()
+ val bw = new BufferedWriter(new FileWriter(swaggerfile))
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val apiValue = RestResult.getFieldJsObject(apiResultRest.getFieldListJsObject("apis")(0), "value")
+ val apidoc = RestResult.getFieldJsObject(apiValue, "apidoc")
+ bw.write(apidoc.toString())
+ bw.close()
+ return swaggerfile
+ }
+
+ override def getSwaggerApiUrl(rr: RunResult): String = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ return apiResultRest.getField("gwApiUrl") + "/path"
+ }
+}
diff --git a/tests/src/test/scala/common/rest/WskRest.scala b/tests/src/test/scala/common/rest/WskRest.scala
index 71551a6..0ae28f9 100644
--- a/tests/src/test/scala/common/rest/WskRest.scala
+++ b/tests/src/test/scala/common/rest/WskRest.scala
@@ -190,8 +190,8 @@ trait DeleteFromCollectionRest extends BaseDeleteFromCollection {
* @param expectedExitCode (optional) the expected exit code for the command
* if the code is anything but DONTCARE_EXIT, assert the code is as expected
*/
- override def delete(entity: String, expectedExitCode: Int = OK.intValue)(implicit wp: WskProps): RestResult = {
- val (ns, entityName) = getNamespaceEntityName(entity)
+ override def delete(name: String, expectedExitCode: Int = OK.intValue)(implicit wp: WskProps): RestResult = {
+ val (ns, entityName) = getNamespaceEntityName(name)
val path = Path(s"$basePath/namespaces/$ns/$noun/$entityName")
val resp = requestEntity(DELETE, path)(wp)
val r = new RestResult(resp.status, getRespData(resp))
@@ -482,7 +482,7 @@ class WskRestTrigger
var body: Map[String, JsValue] = Map(
"lifecycleEvent" -> "CREATE".toJson,
"triggerName" -> s"/$ns/$triggerName".toJson,
- "authKey" -> s"${getAuthKey(wp)}".toJson)
+ "authKey" -> s"${wp.authKey}".toJson)
body = body ++ parameters
val resp = requestEntity(POST, path, paramMap, Some(body.toJson.toString()))
val resultInvoke = new RestResult(resp.status, getRespData(resp))
@@ -971,11 +971,10 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
val r = action match {
case Some(action) => {
val (ns, actionName) = this.getNamespaceEntityName(action)
- val actionUrl = s"${WhiskProperties.getApiHostForAction}/$basePath/web/$ns/default/$actionName.http"
- val actionAuthKey = this.getAuthKey(wp)
+ val actionUrl = s"${WhiskProperties.getApiHostForAction}$basePath/web/$ns/default/$actionName.http"
+ val actionAuthKey = wp.authKey
val testaction = Some(
- ApiAction(name = actionName, namespace = ns, backendUrl = actionUrl, authkey = actionAuthKey))
-
+ new ApiAction(name = actionName, namespace = ns, backendUrl = actionUrl, authkey = actionAuthKey))
val parms = Map[String, JsValue]() ++ { Map("namespace" -> ns.toJson) } ++ {
basepath map { b =>
Map("gatewayBasePath" -> b.toJson)
@@ -1003,14 +1002,16 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
} getOrElse Map[String, JsValue]()
}
- val parm = Map[String, JsValue]("apidoc" -> JsObject(parms)) ++ { Map("__ow_user" -> ns.toJson) } ++ {
+ val spaceguid = if (wp.authKey.contains(":")) wp.authKey.split(":")(0) else wp.authKey
+
+ val parm = Map[String, JsValue]("apidoc" -> JsObject(parms)) ++ {
responsetype map { r =>
Map("responsetype" -> r.toJson)
} getOrElse Map[String, JsValue]()
} ++ {
Map("accesstoken" -> wp.authKey.toJson)
} ++ {
- Map("spaceguid" -> wp.authKey.split(":")(0).toJson)
+ Map("spaceguid" -> spaceguid.toJson)
}
invokeAction(
@@ -1018,10 +1019,44 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
parameters = parm,
blocking = true,
result = true,
+ web = true,
expectedExitCode = expectedExitCode)(wp)
}
case None => {
- new RestResult(NotFound)
+ swagger match {
+ case Some(swaggerFile) => {
+ var file = ""
+ val fileName = swaggerFile.toString()
+ try {
+ file = FileUtils.readFileToString(new File(fileName))
+ } catch {
+ case e: Throwable =>
+ return new RestResult(
+ NotFound,
+ JsObject("error" -> s"Error reading swagger file '$fileName'".toJson).toString())
+ }
+ val parms = Map("namespace" -> s"${wp.namespace}".toJson, "swagger" -> file.toJson)
+ val parm = Map[String, JsValue]("apidoc" -> JsObject(parms)) ++ {
+ responsetype map { r =>
+ Map("responsetype" -> r.toJson)
+ } getOrElse Map[String, JsValue]()
+ } ++ {
+ Map("accesstoken" -> wp.authKey.toJson)
+ } ++ {
+ Map("spaceguid" -> wp.authKey.split(":")(0).toJson)
+ }
+ invokeAction(
+ name = "apimgmt/createApi",
+ parameters = parm,
+ blocking = true,
+ result = true,
+ web = true,
+ expectedExitCode = expectedExitCode)(wp)
+ }
+ case None => {
+ new RestResult(NotFound)
+ }
+ }
}
}
r
@@ -1043,8 +1078,7 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
expectedExitCode: Int = SUCCESS_EXIT,
cliCfgFile: Option[String] = None)(implicit wp: WskProps): RestResult = {
- val parms = Map[String, JsValue]() ++
- Map("__ow_user" -> wp.namespace.toJson) ++ {
+ val parms = Map[String, JsValue]() ++ {
basepathOrApiName map { b =>
Map("basepath" -> b.toJson)
} getOrElse Map[String, JsValue]()
@@ -1061,11 +1095,13 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
} ++ {
Map("spaceguid" -> wp.authKey.split(":")(0).toJson)
}
+
val rr = invokeAction(
name = "apimgmt/getApi",
parameters = parms,
blocking = true,
result = true,
+ web = true,
expectedExitCode = OK.intValue)(wp)
rr
}
@@ -1082,8 +1118,7 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
expectedExitCode: Int = SUCCESS_EXIT,
cliCfgFile: Option[String] = None,
format: Option[String] = None)(implicit wp: WskProps): RestResult = {
- val parms = Map[String, JsValue]() ++
- Map("__ow_user" -> wp.namespace.toJson) ++ {
+ val parms = Map[String, JsValue]() ++ {
basepathOrApiName map { b =>
Map("basepath" -> b.toJson)
} getOrElse Map[String, JsValue]()
@@ -1098,6 +1133,7 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
parameters = parms,
blocking = true,
result = true,
+ web = true,
expectedExitCode = OK.intValue)(wp)
result
}
@@ -1113,7 +1149,7 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
operation: Option[String] = None,
expectedExitCode: Int = SUCCESS_EXIT,
cliCfgFile: Option[String] = None)(implicit wp: WskProps): RestResult = {
- val parms = Map[String, JsValue]() ++ { Map("__ow_user" -> wp.namespace.toJson) } ++ {
+ val parms = Map[String, JsValue]() ++ {
Map("basepath" -> basepathOrApiName.toJson)
} ++ {
relpath map { r =>
@@ -1134,18 +1170,10 @@ class WskRestApi extends RunWskRestCmd with BaseApi {
parameters = parms,
blocking = true,
result = true,
+ web = true,
expectedExitCode = expectedExitCode)(wp)
return rr
}
-
- def getApi(basepathOrApiName: String, params: Map[String, String] = Map(), expectedExitCode: Int = OK.intValue)(
- implicit wp: WskProps): RestResult = {
- val whiskUrl = Uri(WhiskProperties.getApiHostForAction)
- val path = Path(s"/api/${wp.authKey.split(":")(0)}$basepathOrApiName/path")
- val resp = requestEntity(GET, path, params, whiskUrl = whiskUrl)
- val result = new RestResult(resp.status, getRespData(resp))
- result
- }
}
class RunWskRestCmd() extends FlatSpec with RunWskCmd with Matchers with ScalaFutures with WskActorSystem {
@@ -1155,6 +1183,7 @@ class RunWskRestCmd() extends FlatSpec with RunWskCmd with Matchers with ScalaFu
val queueSize = 10
val maxOpenRequest = 1024
val basePath = Path("/api/v1")
+ val systemNamespace = "whisk.system"
val sslConfig = AkkaSSLConfig().mapSettings { s =>
s.withHostnameVerifierClass(classOf[AcceptAllHostNameVerifier].asInstanceOf[Class[HostnameVerifier]])
@@ -1239,11 +1268,6 @@ class RunWskRestCmd() extends FlatSpec with RunWskCmd with Matchers with ScalaFu
}
}
- def getAuthKey(wp: WskProps): String = {
- val authKey = wp.authKey.split(":")
- s"${authKey(0)}:${authKey(1)}"
- }
-
def getParamsAnnos(parameters: Map[String, JsValue] = Map(),
annotations: Map[String, JsValue] = Map(),
parameterFile: Option[String] = None,
@@ -1345,9 +1369,12 @@ class RunWskRestCmd() extends FlatSpec with RunWskCmd with Matchers with ScalaFu
parameterFile: Option[String] = None,
blocking: Boolean = false,
result: Boolean = false,
+ web: Boolean = false,
expectedExitCode: Int = Accepted.intValue)(implicit wp: WskProps): RestResult = {
val (ns, actName) = this.getNamespaceEntityName(name)
- val path = Path(s"$basePath/namespaces/$ns/actions/$actName")
+ val path =
+ if (web) Path(s"$basePath/web/$systemNamespace/$actName.http")
+ else Path(s"$basePath/namespaces/$ns/actions/$actName")
var paramMap = Map("blocking" -> blocking.toString, "result" -> result.toString)
val input = parameterFile map { pf =>
Some(FileUtils.readFileToString(new File(pf)))
@@ -1496,11 +1523,11 @@ class RestResult(var statusCode: StatusCode, var respData: String = "", blocking
}
}
-case class ApiAction(name: String,
- namespace: String,
- backendMethod: String = "POST",
- backendUrl: String,
- authkey: String) {
+class ApiAction(var name: String,
+ var namespace: String,
+ var backendMethod: String = "POST",
+ var backendUrl: String,
+ var authkey: String) {
def toJson(): JsObject = {
return JsObject(
"name" -> name.toJson,
diff --git a/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwCliRoutemgmtActionTests.scala b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwCliRoutemgmtActionTests.scala
new file mode 100644
index 0000000..4f0f131
--- /dev/null
+++ b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwCliRoutemgmtActionTests.scala
@@ -0,0 +1,28 @@
+/*
+ * 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 whisk.core.apigw.actions.test
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import common.Wsk
+
+@RunWith(classOf[JUnitRunner])
+class ApiGwCliRoutemgmtActionTests extends ApiGwRoutemgmtActionTests {
+ override lazy val wsk = new Wsk
+}
diff --git a/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRestRoutemgmtActionTests.scala b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRestRoutemgmtActionTests.scala
new file mode 100644
index 0000000..aff8072
--- /dev/null
+++ b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRestRoutemgmtActionTests.scala
@@ -0,0 +1,31 @@
+/*
+ * 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 whisk.core.apigw.actions.test
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import common.rest.WskRest
+
+/**
+ * Tests for basic CLI usage. Some of these tests require a deployed backend.
+ */
+@RunWith(classOf[JUnitRunner])
+class ApiGwRestRoutemgmtActionTests extends ApiGwRoutemgmtActionTests {
+ override lazy val wsk = new WskRest
+}
diff --git a/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
index fa56de6..57449e6 100644
--- a/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
+++ b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
@@ -24,38 +24,23 @@ import org.scalatest.junit.JUnitRunner
import common.JsHelpers
import common.StreamLogging
import common.TestHelpers
-import common.TestUtils.ANY_ERROR_EXIT
import common.TestUtils.DONTCARE_EXIT
import common.TestUtils.RunResult
import common.TestUtils.SUCCESS_EXIT
-import common.Wsk
+import common.BaseWsk
import common.WskActorSystem
import common.WskAdmin
import common.WskProps
+import common.rest.ApiAction
import common.WskTestHelpers
import spray.json._
import spray.json.DefaultJsonProtocol._
-case class ApiAction(name: String,
- namespace: String,
- backendMethod: String = "POST",
- backendUrl: String,
- authkey: String) {
- def toJson(): JsObject = {
- return JsObject(
- "name" -> name.toJson,
- "namespace" -> namespace.toJson,
- "backendMethod" -> backendMethod.toJson,
- "backendUrl" -> backendUrl.toJson,
- "authkey" -> authkey.toJson)
- }
-}
-
/**
* Tests for basic CLI usage. Some of these tests require a deployed backend.
*/
@RunWith(classOf[JUnitRunner])
-class ApiGwRoutemgmtActionTests
+abstract class ApiGwRoutemgmtActionTests
extends TestHelpers
with BeforeAndAfterAll
with WskActorSystem
@@ -65,7 +50,7 @@ class ApiGwRoutemgmtActionTests
val systemId = "whisk.system"
implicit val wskprops = WskProps(authKey = WskAdmin.listKeys(systemId)(0)._1, namespace = systemId)
- val wsk = new Wsk
+ val wsk: BaseWsk
def getApis(bpOrName: Option[String],
relpath: Option[String] = None,
@@ -299,7 +284,7 @@ class ApiGwRoutemgmtActionTests
val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
val actionAuthKey = testName + "_authkey"
val testaction =
- ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
+ new ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
try {
val createResult = createApi(
@@ -330,7 +315,7 @@ class ApiGwRoutemgmtActionTests
val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
val actionAuthKey = testName + "_authkey"
val testaction =
- ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
+ new ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
try {
val createResult = createApi(
@@ -366,7 +351,7 @@ class ApiGwRoutemgmtActionTests
val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
val actionAuthKey = testName + "_authkey"
val testaction =
- ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
+ new ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
try {
var createResult = createApi(
@@ -393,202 +378,4 @@ class ApiGwRoutemgmtActionTests
deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
}
}
-
- it should "reject apimgmt actions that are invoked with not enough parameters" in {
- val invalidArgs = Seq(
- //getApi
- ("/whisk.system/apimgmt/getApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq()),
- //deleteApi
- (
- "/whisk.system/apimgmt/deleteApi",
- ANY_ERROR_EXIT,
- "Invalid authentication.",
- Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
- (
- "/whisk.system/apimgmt/deleteApi",
- ANY_ERROR_EXIT,
- "basepath is required",
- Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
- (
- "/whisk.system/apimgmt/deleteApi",
- ANY_ERROR_EXIT,
- "When specifying an operation, the path is required",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "basepath",
- "/ApiGwRoutemgmtActionTests_bp",
- "-p",
- "operation",
- "get")),
- //createApi
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "apidoc is required",
- Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "apidoc is missing the namespace field",
- Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", "{}")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "apidoc is missing the gatewayBasePath field",
- Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_"}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "apidoc is missing the gatewayPath field",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp"}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "apidoc is missing the gatewayMethod field",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp"}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "apidoc is missing the action field",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get"}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "action is missing the backendMethod field",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{}}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "action is missing the backendUrl field",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post"}}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "action is missing the namespace field",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL"}}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "action is missing the name field",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_"}}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "action is missing the authkey field",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N"}}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "swagger and gatewayBasePath are mutually exclusive and cannot be specified together",
- Seq(
- "-p",
- "__ow_user",
- "_",
- "-p",
- "accesstoken",
- "TOKEN",
- "-p",
- "apidoc",
- """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N","authkey":"XXXX"},"swagger":{}}""")),
- (
- "/whisk.system/apimgmt/createApi",
- ANY_ERROR_EXIT,
- "apidoc field cannot be parsed. Ensure it is valid JSON",
- Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", "{1:[}}}")))
-
- invalidArgs foreach {
- case (action: String, exitcode: Int, errmsg: String, params: Seq[String]) =>
- val cmd: Seq[String] = Seq(
- "action",
- "invoke",
- action,
- "-i",
- "-b",
- "-r",
- "--apihost",
- wskprops.apihost,
- "--auth",
- wskprops.authKey) ++ params
- val rr = wsk.cli(cmd, expectedExitCode = exitcode)
- rr.stderr should include regex (errmsg)
- }
- }
}
diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwCliTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwCliTests.scala
new file mode 100644
index 0000000..ba886c0
--- /dev/null
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwCliTests.scala
@@ -0,0 +1,33 @@
+/*
+ * 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 whisk.core.cli.test
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import common.Wsk
+import common.TestUtils.SUCCESS_EXIT
+
+/**
+ * Tests for basic CLI usage. Some of these tests require a deployed backend.
+ */
+@RunWith(classOf[JUnitRunner])
+class ApiGwCliTests extends ApiGwTests {
+ override lazy val wsk: common.Wsk = new Wsk
+ override lazy val createCode = SUCCESS_EXIT
+}
diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwRestTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwRestTests.scala
new file mode 100644
index 0000000..8809953
--- /dev/null
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwRestTests.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 whisk.core.cli.test
+
+import akka.http.scaladsl.model.StatusCodes.OK
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+import spray.json.JsObject
+
+import common.rest.WskRest
+import common.rest.RestResult
+import common.TestUtils.RunResult
+
+/**
+ * Tests for testing the CLI "api" subcommand. Most of these tests require a deployed backend.
+ */
+@RunWith(classOf[JUnitRunner])
+class ApiGwRestTests extends ApiGwTests {
+ override lazy val wsk = new WskRest
+ override lazy val createCode = OK.intValue
+
+ override def verifyBadCommands(rr: RunResult, badpath: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val error = RestResult.getField(apiResultRest.respBody, "error")
+ error should include("Error: Resource path must begin with '/'.")
+ }
+
+ override def verifyBadCommandsDelete(rr: RunResult, badpath: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val error = RestResult.getField(apiResultRest.respBody, "error")
+ error should include(s"API deletion failure: API '/basepath' does not exist")
+ }
+
+ override def verifyBadCommandsList(rr: RunResult, badpath: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val apis = apiResultRest.getFieldListJsObject("apis")
+ apis.size shouldBe 0
+ }
+
+ override def verifyInvalidCommands(rr: RunResult, badverb: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val error = apiResultRest.getField("error")
+ error should include(s"Error: Resource verb '${badverb}' not supported")
+ }
+
+ override def verifyInvalidCommandsDelete(rr: RunResult, badverb: String): Unit = {
+ verifyBadCommandsDelete(rr, badverb)
+ }
+
+ override def verifyInvalidCommandsList(rr: RunResult, badverb: String): Unit = {
+ verifyBadCommandsList(rr, badverb)
+ }
+
+ override def verifyNonJsonSwagger(rr: RunResult, filename: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val error = apiResultRest.getField("error")
+ error should include(s"swagger field cannot be parsed. Ensure it is valid JSON")
+ }
+
+ override def verifyMissingField(rr: RunResult): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val error = apiResultRest.getField("error")
+ error should include(s"swagger is missing the basePath field.")
+ }
+
+ override def verifyApiCreated(rr: RunResult): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ apiResultRest.statusCode shouldBe OK
+ }
+
+ def verifyList(rr: RunResult,
+ namespace: String,
+ actionName: String,
+ testurlop: String,
+ testbasepath: String,
+ testrelpath: String,
+ testapiname: String,
+ newEndpoint: String = ""): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val apiValue = RestResult.getFieldJsObject(apiResultRest.getFieldListJsObject("apis")(0), "value")
+ val apidoc = RestResult.getFieldJsObject(apiValue, "apidoc")
+ val basepath = RestResult.getField(apidoc, "basePath")
+ basepath shouldBe testbasepath
+
+ val paths = RestResult.getFieldJsObject(apidoc, "paths")
+ paths.fields.contains(testrelpath) shouldBe true
+
+ val info = RestResult.getFieldJsObject(apidoc, "info")
+ val title = RestResult.getField(info, "title")
+ title shouldBe testapiname
+
+ verifyPaths(paths, testrelpath, testurlop, actionName, namespace)
+
+ if (newEndpoint != "") {
+ verifyPaths(paths, newEndpoint, testurlop, actionName, namespace)
+ }
+ }
+
+ def verifyPaths(paths: JsObject,
+ testrelpath: String,
+ testurlop: String,
+ actionName: String,
+ namespace: String = "") = {
+ val relpath = RestResult.getFieldJsObject(paths, testrelpath)
+ val urlop = RestResult.getFieldJsObject(relpath, testurlop)
+ val openwhisk = RestResult.getFieldJsObject(urlop, "x-openwhisk")
+ val actionN = RestResult.getField(openwhisk, "action")
+ actionN shouldBe actionName
+
+ if (namespace != "") {
+ val namespaceS = RestResult.getField(openwhisk, "namespace")
+ namespaceS shouldBe namespace
+ }
+ }
+
+ override def verifyApiList(rr: RunResult,
+ clinamespace: String,
+ actionName: String,
+ testurlop: String,
+ testbasepath: String,
+ testrelpath: String,
+ testapiname: String): Unit = {
+ verifyList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
+ }
+
+ override def verifyApiGet(rr: RunResult): Unit = {
+ rr.stdout should include regex (s""""operationId":"getPathWithSub_pathsInIt"""")
+ }
+
+ override def verifyApiFullList(rr: RunResult,
+ clinamespace: String,
+ actionName: String,
+ testurlop: String,
+ testbasepath: String,
+ testrelpath: String,
+ testapiname: String): Unit = {
+ verifyList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
+ }
+
+ override def verifyApiFullListDouble(rr: RunResult,
+ clinamespace: String,
+ actionName: String,
+ testurlop: String,
+ testbasepath: String,
+ testrelpath: String,
+ testapiname: String,
+ newEndpoint: String): Unit = {
+ verifyList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname, newEndpoint)
+ }
+
+ override def verifyApiDeleted(rr: RunResult): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ apiResultRest.statusCode shouldBe OK
+ }
+
+ override def verifyApiDeletedRelpath(rr: RunResult,
+ testrelpath: String,
+ testbasepath: String,
+ op: String = ""): Unit = {
+ verifyApiDeleted(rr)
+ }
+
+ override def verifyApiNameGet(rr: RunResult,
+ testbasepath: String,
+ actionName: String,
+ responseType: String = "json"): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+
+ val apiValue = RestResult.getFieldJsObject(apiResultRest.getFieldListJsObject("apis")(0), "value")
+ val apidoc = RestResult.getFieldJsObject(apiValue, "apidoc")
+
+ val config = RestResult.getFieldJsObject(apidoc, "x-ibm-configuration")
+
+ val cors = RestResult.getFieldJsObject(config, "cors")
+ val enabled = RestResult.getFieldJsValue(cors, "enabled").toString()
+ enabled shouldBe "true"
+
+ val basepath = RestResult.getField(apidoc, "basePath")
+ basepath shouldBe testbasepath
+
+ val paths = RestResult.getFieldJsObject(apidoc, "paths")
+ val relpath = RestResult.getFieldJsObject(paths, "/path")
+ val urlop = RestResult.getFieldJsObject(relpath, "get")
+ val openwhisk = RestResult.getFieldJsObject(urlop, "x-openwhisk")
+ val actionN = RestResult.getField(openwhisk, "action")
+ actionN shouldBe actionName
+ rr.stdout should include regex (s""""target-url":".*${actionName}.${responseType}"""")
+ }
+
+ override def verifyInvalidSwagger(rr: RunResult): Unit = {
+ verifyMissingField(rr)
+ }
+
+ override def verifyApiOp(rr: RunResult, testurlop: String, testapiname: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val apiValue = RestResult.getFieldJsObject(apiResultRest.getFieldListJsObject("apis")(0), "value")
+ val apidoc = RestResult.getFieldJsObject(apiValue, "apidoc")
+ val info = RestResult.getFieldJsObject(apidoc, "info")
+ val title = RestResult.getField(info, "title")
+ title shouldBe testapiname
+ val paths = RestResult.getFieldJsObject(apidoc, "paths")
+ val relpath = RestResult.getFieldJsObject(paths, "/")
+ val urlop = RestResult.getFieldJsObject(relpath, testurlop)
+ relpath.fields.contains(testurlop) shouldBe true
+ }
+
+ override def verifyApiBaseRelPath(rr: RunResult, testbasepath: String, testrelpath: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val apiValue = RestResult.getFieldJsObject(apiResultRest.getFieldListJsObject("apis")(0), "value")
+ val apidoc = RestResult.getFieldJsObject(apiValue, "apidoc")
+ val basepath = RestResult.getField(apidoc, "basePath")
+ basepath shouldBe testbasepath
+
+ val paths = RestResult.getFieldJsObject(apidoc, "paths")
+ paths.fields.contains(testrelpath) shouldBe true
+ }
+
+ override def verifyApiOpVerb(rr: RunResult, testurlop: String): Unit = {
+ val apiResultRest = rr.asInstanceOf[RestResult]
+ val apiValue = RestResult.getFieldJsObject(apiResultRest.getFieldListJsObject("apis")(0), "value")
+ val apidoc = RestResult.getFieldJsObject(apiValue, "apidoc")
+ val paths = RestResult.getFieldJsObject(apidoc, "paths")
+ val relpath = RestResult.getFieldJsObject(paths, "/")
+ val urlop = RestResult.getFieldJsObject(relpath, testurlop)
+ relpath.fields.contains(testurlop) shouldBe true
+ }
+
+ override def verifyInvalidKey(rr: RunResult): Unit = {
+ rr.stderr should include("A valid auth key is required")
+ }
+
+}
diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
index 9f152b0..145ea6b 100644
--- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
@@ -20,149 +20,147 @@ package whisk.core.cli.test
import java.io.File
import java.io.BufferedWriter
import java.io.FileWriter
-import java.time.Instant
-
-import scala.collection.mutable.ArrayBuffer
-import scala.concurrent.duration._
import org.junit.runner.RunWith
-import org.scalatest.BeforeAndAfterAll
-import org.scalatest.BeforeAndAfterEach
import org.scalatest.junit.JUnitRunner
-import common.TestHelpers
import common.TestUtils._
import common.TestUtils
-import common.WhiskProperties
-import common.Wsk
import common.WskProps
-import common.WskTestHelpers
/**
* Tests for testing the CLI "api" subcommand. Most of these tests require a deployed backend.
*/
@RunWith(classOf[JUnitRunner])
-class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach with BeforeAndAfterAll {
+abstract class ApiGwTests extends BaseApiGwTests {
- implicit val wskprops = WskProps()
- val wsk = new Wsk
val clinamespace = wsk.namespace.whois()
+ val createCode: Int
- // This test suite makes enough CLI invocations in 60 seconds to trigger the OpenWhisk
- // throttling restriction. To avoid CLI failures due to being throttled, track the
- // CLI invocation calls and when at the throttle limit, pause the next CLI invocation
- // with exactly enough time to relax the throttling.
- val maxActionsPerMin = WhiskProperties.getMaxActionInvokesPerMinute()
- val invocationTimes = new ArrayBuffer[Instant]()
-
- // Custom CLI properties file
- val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
-
- /**
- * Expected to be called before each test.
- * Assumes that each test will not invoke more than 5 actions and
- * settle the throttle when there isn't enough capacity to handle the test.
- */
- def checkThrottle(maxInvocationsBeforeThrottle: Int = maxActionsPerMin, expectedActivationsPerTest: Int = 5) = {
- val t = Instant.now
- val tminus60 = t.minusSeconds(60)
- val invocationsLast60Seconds = invocationTimes.filter(_.isAfter(tminus60)).sorted
- val invocationCount = invocationsLast60Seconds.length
- println(s"Action invokes within last minute: ${invocationCount}")
-
- if (invocationCount >= maxInvocationsBeforeThrottle) {
- // Instead of waiting a fixed 60 seconds to settle the throttle,
- // calculate a wait time that will clear out about half of the
- // current invocations (assuming even distribution) from the
- // next 60 second period.
- val oldestInvocationInLast60Seconds = invocationsLast60Seconds.head
-
- // Take the oldest invocation time in this 60 second period. To clear
- // this invocation from the next 60 second period, the wait time will be
- // (60sec - oldest invocation's delta time away from the period end).
- // This will clear all of the invocations from the next period at the
- // expense of potentially waiting uncessarily long. Instead, this calculation
- // halves the delta time as a compromise.
- val throttleTime = 60.seconds.toMillis - ((t.toEpochMilli - oldestInvocationInLast60Seconds.toEpochMilli) / 2)
- println(s"Waiting ${throttleTime} milliseconds to settle the throttle")
- Thread.sleep(throttleTime)
- }
+ def verifyBadCommands(rr: RunResult, badpath: String): Unit = {
+ rr.stderr should include(s"'${badpath}' must begin with '/'")
+ }
+
+ def verifyBadCommandsDelete(rr: RunResult, badpath: String): Unit = {
+ verifyBadCommands(rr, badpath)
+ }
+
+ def verifyBadCommandsList(rr: RunResult, badpath: String): Unit = {
+ verifyBadCommands(rr, badpath)
+ }
+
+ def verifyInvalidCommands(rr: RunResult, badverb: String): Unit = {
+ rr.stderr should include(s"'${badverb}' is not a valid API verb. Valid values are:")
+ }
+
+ def verifyInvalidCommandsDelete(rr: RunResult, badverb: String): Unit = {
+ verifyInvalidCommands(rr, badverb)
+ }
+
+ def verifyInvalidCommandsList(rr: RunResult, badverb: String): Unit = {
+ verifyInvalidCommands(rr, badverb)
+ }
+
+ def verifyNonJsonSwagger(rr: RunResult, filename: String): Unit = {
+ rr.stderr should include(s"Error parsing swagger file '${filename}':")
+ }
+
+ def verifyMissingField(rr: RunResult): Unit = {
+ rr.stderr should include(s"Swagger file is invalid (missing basePath, info, paths, or swagger fields")
+ }
+
+ def verifyApiCreated(rr: RunResult): Unit = {
+ rr.stdout should include("ok: created API")
+ }
- invocationTimes += Instant.now
+ def verifyApiList(rr: RunResult,
+ clinamespace: String,
+ actionName: String,
+ testurlop: String,
+ testbasepath: String,
+ testrelpath: String,
+ testapiname: String): Unit = {
+ rr.stdout should include("ok: APIs")
+ rr.stdout should include regex (s"Action:\\s+/${clinamespace}/${actionName}\n")
+ rr.stdout should include regex (s"Verb:\\s+${testurlop}\n")
+ rr.stdout should include regex (s"Base path:\\s+${testbasepath}\n")
+ rr.stdout should include regex (s"Path:\\s+${testrelpath}\n")
+ rr.stdout should include regex (s"API Name:\\s+${testapiname}\n")
+ rr.stdout should include regex (s"URL:\\s+")
+ rr.stdout should include(testbasepath + testrelpath)
}
- override def beforeEach() = {
- //checkThrottle()
+ def verifyApiBaseRelPath(rr: RunResult, testbasepath: String, testrelpath: String): Unit = {
+ rr.stdout should include(testbasepath + testrelpath)
}
- /*
- * Create a CLI properties file for use by the tests
- */
- override def beforeAll() = {
- cliWskPropsFile.deleteOnExit()
- val wskprops = WskProps(token = "SOME TOKEN")
- wskprops.writeFile(cliWskPropsFile)
- println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}")
+ def verifyApiGet(rr: RunResult): Unit = {
+ rr.stdout should include regex (s""""operationId":\\s+"getPathWithSub_pathsInIt"""")
}
- /*
- * Forcibly clear the throttle so that downstream tests are not affected by
- * this test suite
- */
- override def afterAll() = {
- // Check and settle the throttle so that this test won't cause issues with and follow on tests
- checkThrottle(30)
+ def verifyApiFullList(rr: RunResult,
+ clinamespace: String,
+ actionName: String,
+ testurlop: String,
+ testbasepath: String,
+ testrelpath: String,
+ testapiname: String): Unit = {
+
+ rr.stdout should include("ok: APIs")
+ if (clinamespace == "") {
+ rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+ } else {
+ rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+ }
+ rr.stdout should include(testbasepath + testrelpath)
+
+ }
+
+ def verifyApiFullListDouble(rr: RunResult,
+ clinamespace: String,
+ actionName: String,
+ testurlop: String,
+ testbasepath: String,
+ testrelpath: String,
+ testapiname: String,
+ newEndpoint: String): Unit = {
+ verifyApiFullList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
+ rr.stdout should include(testbasepath + newEndpoint)
+ }
+
+ def verifyApiDeleted(rr: RunResult): Unit = {
+ rr.stdout should include("ok: deleted API")
}
- def apiCreate(basepath: Option[String] = None,
- relpath: Option[String] = None,
- operation: Option[String] = None,
- action: Option[String] = None,
- apiname: Option[String] = None,
- swagger: Option[String] = None,
- responsetype: Option[String] = None,
- expectedExitCode: Int = SUCCESS_EXIT,
- cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()))(
- implicit wskpropsOverride: WskProps): RunResult = {
-
- checkThrottle()
- wsk.api.create(basepath, relpath, operation, action, apiname, swagger, responsetype, expectedExitCode, cliCfgFile)(
- wskpropsOverride)
+ def verifyApiDeletedRelpath(rr: RunResult, testrelpath: String, testbasepath: String, op: String = ""): Unit = {
+ if (op != "")
+ rr.stdout should include("ok: deleted " + testrelpath + " " + op.toUpperCase() + " from " + testbasepath)
+ else
+ rr.stdout should include("ok: deleted " + testrelpath + " from " + testbasepath)
}
- def apiList(basepathOrApiName: Option[String] = None,
- relpath: Option[String] = None,
- operation: Option[String] = None,
- limit: Option[Int] = None,
- since: Option[Instant] = None,
- full: Option[Boolean] = None,
- nameSort: Option[Boolean] = None,
- expectedExitCode: Int = SUCCESS_EXIT,
- cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
-
- checkThrottle()
- wsk.api.list(basepathOrApiName, relpath, operation, limit, since, full, nameSort, expectedExitCode, cliCfgFile)
+ def verifyApiNameGet(rr: RunResult, testbasepath: String, actionName: String, responseType: String = "json"): Unit = {
+ rr.stdout should include(testbasepath)
+ rr.stdout should include(s"${actionName}")
+ rr.stdout should include regex (""""cors":\s*\{\s*\n\s*"enabled":\s*true""")
+ rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
}
- def apiGet(basepathOrApiName: Option[String] = None,
- full: Option[Boolean] = None,
- expectedExitCode: Int = SUCCESS_EXIT,
- cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()),
- format: Option[String] = None): RunResult = {
+ def verifyInvalidSwagger(rr: RunResult): Unit = {
+ rr.stderr should include(s"Swagger file is invalid")
+ }
- checkThrottle()
- wsk.api.get(basepathOrApiName, full, expectedExitCode, cliCfgFile, format)
+ def verifyApiOp(rr: RunResult, testurlop: String, testapiname: String): Unit = {
+ rr.stdout should include regex (s"\\s+${testurlop}\\s+${testapiname}\\s+")
}
- def apiDelete(basepathOrApiName: String,
- relpath: Option[String] = None,
- operation: Option[String] = None,
- expectedExitCode: Int = SUCCESS_EXIT,
- cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
+ def verifyApiOpVerb(rr: RunResult, testurlop: String): Unit = {
+ rr.stdout should include regex (s"Verb:\\s+${testurlop}")
+ }
- checkThrottle()
- wsk.api.delete(basepathOrApiName, relpath, operation, expectedExitCode, cliCfgFile)
+ def verifyInvalidKey(rr: RunResult): Unit = {
+ rr.stderr should include("The supplied authentication is invalid")
}
behavior of "Wsk api"
@@ -176,21 +174,21 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some("GET"),
action = Some("action"),
expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"'${badpath}' must begin with '/'")
+ verifyBadCommands(rr, badpath)
rr = apiDelete(
basepathOrApiName = "/basepath",
relpath = Some(badpath),
operation = Some("GET"),
expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"'${badpath}' must begin with '/'")
+ verifyBadCommandsDelete(rr, badpath)
rr = apiList(
basepathOrApiName = Some("/basepath"),
relpath = Some(badpath),
operation = Some("GET"),
expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"'${badpath}' must begin with '/'")
+ verifyBadCommandsList(rr, badpath)
}
it should "reject an api commands with an invalid verb parameter" in {
@@ -202,28 +200,28 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(badverb),
action = Some("action"),
expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"'${badverb}' is not a valid API verb. Valid values are:")
+ verifyInvalidCommands(rr, badverb)
rr = apiDelete(
basepathOrApiName = "/basepath",
relpath = Some("/path"),
operation = Some(badverb),
expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"'${badverb}' is not a valid API verb. Valid values are:")
+ verifyInvalidCommandsDelete(rr, badverb)
rr = apiList(
basepathOrApiName = Some("/basepath"),
relpath = Some("/path"),
operation = Some(badverb),
expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"'${badverb}' is not a valid API verb. Valid values are:")
+ verifyInvalidCommandsList(rr, badverb)
}
it should "reject an api create command that specifies a nonexistent configuration file" in {
val configfile = "/nonexistent/file"
val rr = apiCreate(swagger = Some(configfile), expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"Error reading swagger file '${configfile}':")
+ rr.stderr should include(s"Error reading swagger file '${configfile}'")
}
it should "reject an api create command specifying a non-JSON configuration file" in {
@@ -236,7 +234,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
bw.close()
val rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"Error parsing swagger file '${filename}':")
+ verifyNonJsonSwagger(rr, filename)
}
it should "reject an api create command specifying a non-swagger JSON configuration file" in {
@@ -261,7 +259,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
bw.close()
val rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include(s"Swagger file is invalid (missing basePath, info, paths, or swagger fields")
+ verifyMissingField(rr)
}
it should "verify full list output" in {
@@ -276,7 +274,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
println("cli namespace: " + clinamespace)
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -285,21 +283,14 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
action = Some(actionName),
apiname = Some(testapiname))
println("api create: " + rr.stdout)
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(
basepathOrApiName = Some(testbasepath),
relpath = Some(testrelpath),
operation = Some(testurlop),
full = Some(true))
println("api list: " + rr.stdout)
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"Action:\\s+/${clinamespace}/${actionName}\n")
- rr.stdout should include regex (s"Verb:\\s+${testurlop}\n")
- rr.stdout should include regex (s"Base path:\\s+${testbasepath}\n")
- rr.stdout should include regex (s"Path:\\s+${testrelpath}\n")
- rr.stdout should include regex (s"API Name:\\s+${testapiname}\n")
- rr.stdout should include regex (s"URL:\\s+")
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath)
@@ -319,7 +310,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -327,15 +318,13 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiFullList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
rr = apiGet(basepathOrApiName = Some(testbasepath))
- rr.stdout should include regex (s""""operationId":\\s+"getPathWithSub_pathsInIt"""")
+ verifyApiGet(rr)
val deleteresult = apiDelete(basepathOrApiName = testbasepath)
- deleteresult.stdout should include("ok: deleted API")
+ verifyApiDeleted(deleteresult)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -353,7 +342,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -361,12 +350,9 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiGet(basepathOrApiName = Some(testapiname))
- rr.stdout should include(testbasepath)
- rr.stdout should include(s"${actionName}")
- rr.stdout should include regex (""""cors":\s*\{\s*\n\s*"enabled":\s*true""")
- rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.json""")
+ verifyApiNameGet(rr, testbasepath, actionName)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -384,7 +370,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -392,9 +378,9 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiDelete(basepathOrApiName = testapiname)
- rr.stdout should include("ok: deleted API")
+ verifyApiDeleted(rr)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -412,7 +398,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -420,9 +406,9 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiDelete(basepathOrApiName = testbasepath)
- rr.stdout should include("ok: deleted API")
+ verifyApiDeleted(rr)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -441,7 +427,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -449,19 +435,24 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiCreate(
basepath = Some(testbasepath),
relpath = Some(newEndpoint),
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
- rr.stdout should include(testbasepath + newEndpoint)
+ verifyApiFullListDouble(
+ rr,
+ clinamespace,
+ actionName,
+ testurlop,
+ testbasepath,
+ newEndpoint,
+ testapiname,
+ newEndpoint)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -479,14 +470,12 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
val swaggerPath = TestUtils.getTestApiGwFilename("testswaggerdoc1")
try {
var rr = apiCreate(swagger = Some(swaggerPath))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
println("list stdout: " + rr.stdout)
println("list stderr: " + rr.stderr)
- rr.stdout should include("ok: APIs")
- // Actual CLI namespace will vary from local dev to automated test environments, so don't check
- rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiFullList(rr, "", actionName, testurlop, testbasepath, testrelpath, testapiname)
+
} finally {
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
}
@@ -506,7 +495,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -514,14 +503,14 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiCreate(
basepath = Some(testbasepath2),
relpath = Some(testrelpath),
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname2))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
// Update both APIs - each with a new endpoint
rr = apiCreate(
@@ -529,25 +518,36 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
relpath = Some(newEndpoint),
operation = Some(testurlop),
action = Some(actionName))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiCreate(
basepath = Some(testbasepath2),
relpath = Some(newEndpoint),
operation = Some(testurlop),
action = Some(actionName))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
- rr.stdout should include(testbasepath + newEndpoint)
+ verifyApiFullListDouble(
+ rr,
+ clinamespace,
+ actionName,
+ testurlop,
+ testbasepath,
+ testrelpath,
+ testapiname,
+ newEndpoint)
rr = apiList(basepathOrApiName = Some(testbasepath2))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath2 + testrelpath)
- rr.stdout should include(testbasepath2 + newEndpoint)
+ verifyApiFullListDouble(
+ rr,
+ clinamespace,
+ actionName,
+ testurlop,
+ testbasepath2,
+ testrelpath,
+ testapiname2,
+ newEndpoint)
+
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -570,7 +570,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -578,13 +578,11 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiFullList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
val deleteresult = apiDelete(basepathOrApiName = testbasepath)
- deleteresult.stdout should include("ok: deleted API")
+ verifyApiDeleted(deleteresult)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -604,7 +602,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
println("api create stdout: " + rr.stdout)
println("api create stderr: " + rr.stderr)
- rr.stderr should include(s"Swagger file is invalid")
+ verifyInvalidSwagger(rr)
} finally {
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
}
@@ -621,7 +619,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -629,20 +627,18 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
var rr2 = apiCreate(
basepath = Some(testbasepath),
relpath = Some(testnewrelpath),
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr2.stdout should include("ok: created API")
+ verifyApiCreated(rr2)
rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath))
- rr.stdout should include("ok: deleted " + testrelpath + " from " + testbasepath)
+ verifyApiDeletedRelpath(rr, testrelpath, testbasepath)
rr2 = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testnewrelpath))
- rr2.stdout should include("ok: APIs")
- rr2.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr2.stdout should include(testbasepath + testnewrelpath)
+ verifyApiFullList(rr2, clinamespace, actionName, testurlop, testbasepath, testnewrelpath, testapiname)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -661,7 +657,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -669,22 +665,22 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiCreate(
basepath = Some(testbasepath),
relpath = Some(testrelpath),
operation = Some(testurlop2),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiFullList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
+ verifyApiFullList(rr, clinamespace, actionName, testurlop2, testbasepath, testrelpath, testapiname)
rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath), operation = Some(testurlop2))
- rr.stdout should include("ok: deleted " + testrelpath + " " + "POST" + " from " + testbasepath)
+ verifyApiDeletedRelpath(rr, testrelpath, testbasepath, testurlop2)
+
rr = apiList(basepathOrApiName = Some(testbasepath))
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+ verifyApiFullList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -697,6 +693,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
val testrelpath = "/whisk_system/utils/echo"
val testrelpath2 = "/whisk_system/utils/split"
val testurlop = "get"
+ val testurlop2 = "post"
val testapiname = testName + " API Name"
val actionName = "test1a"
val swaggerPath = TestUtils.getTestApiGwFilename(s"testswaggerdoc2")
@@ -704,13 +701,10 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
var rr = apiCreate(swagger = Some(swaggerPath))
println("api create stdout: " + rr.stdout)
println("api create stderror: " + rr.stderr)
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath))
- rr.stdout should include("ok: APIs")
- // Actual CLI namespace will vary from local dev to automated test environments, so don't check
- rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
- rr.stdout should include(testbasepath + testrelpath2)
+ verifyApiFullList(rr, "", actionName, testurlop, testbasepath, testrelpath, testapiname)
+ verifyApiFullList(rr, "", actionName, testurlop2, testbasepath, testrelpath2, testapiname)
} finally {
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
}
@@ -729,7 +723,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
var rr = apiCreate(
basepath = Some(testbasepath),
@@ -737,30 +731,24 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiFullList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
rr = apiCreate(
basepath = Some(testbasepath2),
relpath = Some(testrelpath),
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname2))
- rr.stdout should include("ok: created API")
+ verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath2 + testrelpath)
+ verifyApiFullList(rr, clinamespace, actionName, testurlop, testbasepath2, testrelpath, testapiname2)
rr = apiDelete(basepathOrApiName = testbasepath2)
- rr.stdout should include("ok: deleted API")
+ verifyApiDeleted(rr)
rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
- rr.stdout should include("ok: APIs")
- rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiFullList(rr, clinamespace, actionName, testurlop, testbasepath, testrelpath, testapiname)
rr = apiDelete(basepathOrApiName = testbasepath)
- rr.stdout should include("ok: deleted API")
+ verifyApiDeleted(rr)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -768,55 +756,6 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
}
}
- it should "reject an API created with a non-existent action" in {
- val testName = "CLI_APIGWTEST15"
- val testbasepath = "/" + testName + "_bp"
- val testrelpath = "/path"
- val testnewrelpath = "/path_new"
- val testurlop = "get"
- val testapiname = testName + " API Name"
- val actionName = testName + "_action"
- try {
- val rr = apiCreate(
- basepath = Some(testbasepath),
- relpath = Some(testrelpath),
- operation = Some(testurlop),
- action = Some(actionName),
- apiname = Some(testapiname),
- expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include("does not exist")
- } finally {
- apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
- }
- }
-
- it should "reject an API created with an action that is not a web action" in {
- val testName = "CLI_APIGWTEST16"
- val testbasepath = "/" + testName + "_bp"
- val testrelpath = "/path"
- val testnewrelpath = "/path_new"
- val testurlop = "get"
- val testapiname = testName + " API Name"
- val actionName = testName + "_action"
- try {
- // Create the action for the API. It must NOT be a "web-action" action for this test
- val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT)
-
- val rr = apiCreate(
- basepath = Some(testbasepath),
- relpath = Some(testrelpath),
- operation = Some(testurlop),
- action = Some(actionName),
- apiname = Some(testapiname),
- expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include("is not a web action")
- } finally {
- wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
- apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
- }
- }
-
it should "verify API with http response type " in {
val testName = "CLI_APIGWTEST17"
val testbasepath = "/" + testName + "_bp"
@@ -829,133 +768,25 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API. It must be a "web-action" action.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
- apiCreate(
- basepath = Some(testbasepath),
- relpath = Some(testrelpath),
- operation = Some(testurlop),
- action = Some(actionName),
- apiname = Some(testapiname),
- responsetype = Some(responseType)).stdout should include("ok: created API")
-
- val rr = apiGet(basepathOrApiName = Some(testapiname))
- rr.stdout should include(testbasepath)
- rr.stdout should include(s"${actionName}")
- rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
- } finally {
- wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
- apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
- }
- }
-
- it should "reject API export when export type is invalid" in {
- val testName = "CLI_APIGWTEST18"
- val testbasepath = "/" + testName + "_bp"
-
- val rr = apiGet(basepathOrApiName = Some(testbasepath), format = Some("BadType"), expectedExitCode = ANY_ERROR_EXIT)
- rr.stderr should include("Invalid format type")
- }
-
- it should "successfully export an API in YAML format" in {
- val testName = "CLI_APIGWTEST19"
- val testbasepath = "/" + testName + "_bp"
- val testrelpath = "/path"
- val testnewrelpath = "/path_new"
- val testurlop = "get"
- val testapiname = testName + " API Name"
- val actionName = testName + "_action"
- val responseType = "http"
- try {
- // Create the action for the API. It must be a "web-action" action.
- val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
- apiCreate(
- basepath = Some(testbasepath),
- relpath = Some(testrelpath),
- operation = Some(testurlop),
- action = Some(actionName),
- apiname = Some(testapiname),
- responsetype = Some(responseType)).stdout should include("ok: created API")
-
- val rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("yaml"))
- rr.stdout should include(s"basePath: ${testbasepath}")
- } finally {
- wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
- apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
- }
- }
-
- it should "successfully export an API when JSON format is explcitly specified" in {
- val testName = "CLI_APIGWTEST20"
- val testbasepath = "/" + testName + "_bp"
- val testrelpath = "/path"
- val testnewrelpath = "/path_new"
- val testurlop = "get"
- val testapiname = testName + " API Name"
- val actionName = testName + "_action"
- val responseType = "http"
- try {
- // Create the action for the API. It must be a "web-action" action.
- val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
- apiCreate(
+ var rr = apiCreate(
basepath = Some(testbasepath),
relpath = Some(testrelpath),
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname),
- responsetype = Some(responseType)).stdout should include("ok: created API")
+ responsetype = Some(responseType))
+ verifyApiCreated(rr)
- val rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("json"))
- rr.stdout should include(testbasepath)
- rr.stdout should include(s"${actionName}")
- rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
+ rr = apiGet(basepathOrApiName = Some(testapiname))
+ verifyApiNameGet(rr, testbasepath, actionName, responseType)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
}
}
- it should "successfully create an API from a YAML formatted API configuration file" in {
- val testName = "CLI_APIGWTEST21"
- val testbasepath = "/bp"
- val testrelpath = "/rp"
- val testurlop = "get"
- val testapiname = testbasepath
- val actionName = "webhttpecho"
- val swaggerPath = TestUtils.getTestApiGwFilename(s"local.api.yaml")
- try {
- var rr = apiCreate(swagger = Some(swaggerPath))
- println("api create stdout: " + rr.stdout)
- println("api create stderror: " + rr.stderr)
- rr.stdout should include("ok: created API")
- rr = apiList(basepathOrApiName = Some(testbasepath))
- rr.stdout should include("ok: APIs")
- // Actual CLI namespace will vary from local dev to automated test environments, so don't check
- rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
- rr.stdout should include(testbasepath + testrelpath)
- } finally {
- apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
- }
- }
-
- it should "reject creation of an API from invalid YAML formatted API configuration file" in {
- val testName = "CLI_APIGWTEST22"
- val testbasepath = "/" + testName + "_bp"
- val swaggerPath = TestUtils.getTestApiGwFilename(s"local.api.bad.yaml")
- try {
- val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
- println("api create stdout: " + rr.stdout)
- println("api create stderror: " + rr.stderr)
- rr.stderr should include("Unable to parse YAML configuration file")
- } finally {
- apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
- }
- }
-
it should "reject deletion of a non-existent api" in {
val nonexistentApi = "/not-there"
@@ -975,21 +806,21 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
var rr = apiCreate(swagger = Some(swaggerPath))
println("api create stdout: " + rr.stdout)
println("api create stderror: " + rr.stderr)
- rr.stdout should include("ok: created API")
+ this.verifyApiCreated(rr)
rr = apiList(basepathOrApiName = Some(testbasepath))
println("api list:\n" + rr.stdout)
testops foreach { testurlop =>
- rr.stdout should include regex (s"\\s+${testurlop}\\s+${testapiname}\\s+")
+ verifyApiOp(rr, testurlop, testapiname)
}
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiBaseRelPath(rr, testbasepath, testrelpath)
rr = apiList(basepathOrApiName = Some(testbasepath), full = Some(true))
println("api full list:\n" + rr.stdout)
testops foreach { testurlop =>
- rr.stdout should include regex (s"Verb:\\s+${testurlop}")
+ verifyApiOpVerb(rr, testurlop)
}
- rr.stdout should include(testbasepath + testrelpath)
+ verifyApiBaseRelPath(rr, testbasepath, testrelpath)
} finally {
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
@@ -1007,58 +838,22 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
try {
// Create the action for the API.
val file = TestUtils.getTestActionFilename(s"echo.js")
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = createCode, web = Some("true"))
// Set an invalid auth key
val badWskProps = WskProps(authKey = "bad-auth-key")
- apiCreate(
+ val rr = apiCreate(
basepath = Some(testbasepath),
relpath = Some(testrelpath),
operation = Some(testurlop),
action = Some(actionName),
apiname = Some(testapiname),
- expectedExitCode = ANY_ERROR_EXIT)(badWskProps).stderr should include("The supplied authentication is invalid")
+ expectedExitCode = ANY_ERROR_EXIT)(badWskProps)
+ verifyInvalidKey(rr)
} finally {
wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
}
}
-
- it should "list api alphabetically by Base/Rel/Verb" in {
- val baseName = "/BaseTestPathApiList"
- val actionName = "actionName"
- val file = TestUtils.getTestActionFilename(s"echo-web-http.js")
- try {
- // Create Action for apis
- var action =
- wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
- println("action creation: " + action.stdout)
- // Create apis
- for (i <- 1 to 3) {
- val base = s"$baseName$i"
- var api = apiCreate(
- basepath = Some(base),
- relpath = Some("/relPath"),
- operation = Some("GET"),
- action = Some(actionName))
- println("api creation: " + api.stdout)
- }
- val original = apiList(nameSort = Some(true)).stdout
- val originalFull = apiList(full = Some(true), nameSort = Some(true)).stdout
- val scalaSorted = List(s"${baseName}1" + "/", s"${baseName}2" + "/", s"${baseName}3" + "/")
- val regex = s"${baseName}[1-3]/".r
- val list = (regex.findAllMatchIn(original)).toList
- val listFull = (regex.findAllMatchIn(originalFull)).toList
-
- scalaSorted.toString shouldEqual list.toString
- scalaSorted.toString shouldEqual listFull.toString
- } finally {
- // Clean up Apis
- for (i <- 1 to 3) {
- apiDelete(basepathOrApiName = s"${baseName}$i", expectedExitCode = DONTCARE_EXIT)
- }
- wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
- }
- }
}
diff --git a/tests/src/test/scala/whisk/core/cli/test/BaseApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/BaseApiGwTests.scala
new file mode 100644
index 0000000..f55ab79
--- /dev/null
+++ b/tests/src/test/scala/whisk/core/cli/test/BaseApiGwTests.scala
@@ -0,0 +1,165 @@
+/*
+ * 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 whisk.core.cli.test
+
+import java.io.File
+import java.time.Instant
+
+import scala.collection.mutable.ArrayBuffer
+import scala.concurrent.duration._
+
+import org.junit.runner.RunWith
+
+import org.scalatest.BeforeAndAfterAll
+import org.scalatest.BeforeAndAfterEach
+import org.scalatest.junit.JUnitRunner
+
+import common.TestHelpers
+import common.TestUtils._
+import common.WhiskProperties
+import common.BaseWsk
+import common.WskProps
+import common.WskTestHelpers
+
+/**
+ * Tests for testing the CLI "api" subcommand. Most of these tests require a deployed backend.
+ */
+@RunWith(classOf[JUnitRunner])
+abstract class BaseApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach with BeforeAndAfterAll {
+
+ implicit val wskprops = WskProps()
+ val wsk: BaseWsk
+
+ // This test suite makes enough CLI invocations in 60 seconds to trigger the OpenWhisk
+ // throttling restriction. To avoid CLI failures due to being throttled, track the
+ // CLI invocation calls and when at the throttle limit, pause the next CLI invocation
+ // with exactly enough time to relax the throttling.
+ val maxActionsPerMin = WhiskProperties.getMaxActionInvokesPerMinute()
+ val invocationTimes = new ArrayBuffer[Instant]()
+
+ // Custom CLI properties file
+ val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
+
+ /**
+ * Expected to be called before each test.
+ * Assumes that each test will not invoke more than 5 actions and
+ * settle the throttle when there isn't enough capacity to handle the test.
+ */
+ def checkThrottle(maxInvocationsBeforeThrottle: Int = maxActionsPerMin, expectedActivationsPerTest: Int = 5) = {
+ val t = Instant.now
+ val tminus60 = t.minusSeconds(60)
+ val invocationsLast60Seconds = invocationTimes.filter(_.isAfter(tminus60)).sorted
+ val invocationCount = invocationsLast60Seconds.length
+ println(s"Action invokes within last minute: ${invocationCount}")
+
+ if (invocationCount >= maxInvocationsBeforeThrottle) {
+ // Instead of waiting a fixed 60 seconds to settle the throttle,
+ // calculate a wait time that will clear out about half of the
+ // current invocations (assuming even distribution) from the
+ // next 60 second period.
+ val oldestInvocationInLast60Seconds = invocationsLast60Seconds.head
+
+ // Take the oldest invocation time in this 60 second period. To clear
+ // this invocation from the next 60 second period, the wait time will be
+ // (60sec - oldest invocation's delta time away from the period end).
+ // This will clear all of the invocations from the next period at the
+ // expense of potentially waiting uncessarily long. Instead, this calculation
+ // halves the delta time as a compromise.
+ val throttleTime = 60.seconds.toMillis - ((t.toEpochMilli - oldestInvocationInLast60Seconds.toEpochMilli) / 2)
+ println(s"Waiting ${throttleTime} milliseconds to settle the throttle")
+ Thread.sleep(throttleTime)
+ }
+
+ invocationTimes += Instant.now
+ }
+
+ override def beforeEach() = {
+ //checkThrottle()
+ }
+
+ /*
+ * Create a CLI properties file for use by the tests
+ */
+ override def beforeAll() = {
+ cliWskPropsFile.deleteOnExit()
+ val wskprops = WskProps(token = "SOME TOKEN")
+ wskprops.writeFile(cliWskPropsFile)
+ println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}")
+ }
+
+ /*
+ * Forcibly clear the throttle so that downstream tests are not affected by
+ * this test suite
+ */
+ override def afterAll() = {
+ // Check and settle the throttle so that this test won't cause issues with and follow on tests
+ checkThrottle(30)
+ }
+
+ def apiCreate(basepath: Option[String] = None,
+ relpath: Option[String] = None,
+ operation: Option[String] = None,
+ action: Option[String] = None,
+ apiname: Option[String] = None,
+ swagger: Option[String] = None,
+ responsetype: Option[String] = None,
+ expectedExitCode: Int = SUCCESS_EXIT,
+ cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()))(
+ implicit wskpropsOverride: WskProps): RunResult = {
+
+ println("parmssss is fdasdadasdddddddddsfsd")
+ checkThrottle()
+ println("create is fdasdadasdddddddddsfsd")
+ wsk.api.create(basepath, relpath, operation, action, apiname, swagger, responsetype, expectedExitCode, cliCfgFile)(
+ wskpropsOverride)
+ }
+
+ def apiList(basepathOrApiName: Option[String] = None,
+ relpath: Option[String] = None,
+ operation: Option[String] = None,
+ limit: Option[Int] = None,
+ since: Option[Instant] = None,
+ full: Option[Boolean] = None,
+ nameSort: Option[Boolean] = None,
+ expectedExitCode: Int = SUCCESS_EXIT,
+ cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
+
+ checkThrottle()
+ wsk.api.list(basepathOrApiName, relpath, operation, limit, since, full, nameSort, expectedExitCode, cliCfgFile)
+ }
+
+ def apiGet(basepathOrApiName: Option[String] = None,
+ full: Option[Boolean] = None,
+ expectedExitCode: Int = SUCCESS_EXIT,
+ cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()),
+ format: Option[String] = None): RunResult = {
+
+ checkThrottle()
+ wsk.api.get(basepathOrApiName, full, expectedExitCode, cliCfgFile, format)
+ }
+
+ def apiDelete(basepathOrApiName: String,
+ relpath: Option[String] = None,
+ operation: Option[String] = None,
+ expectedExitCode: Int = SUCCESS_EXIT,
+ cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
+
+ checkThrottle()
+ wsk.api.delete(basepathOrApiName, relpath, operation, expectedExitCode, cliCfgFile)
+ }
+}
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskCliApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskCliApiGwTests.scala
new file mode 100644
index 0000000..088b6c5
--- /dev/null
+++ b/tests/src/test/scala/whisk/core/cli/test/WskCliApiGwTests.scala
@@ -0,0 +1,438 @@
+/*
+ * 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 whisk.core.cli.test
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+
+import common.JsHelpers
+import common.StreamLogging
+import common.TestUtils
+import common.TestUtils.ANY_ERROR_EXIT
+import common.TestUtils.DONTCARE_EXIT
+import common.TestUtils.SUCCESS_EXIT
+import common.Wsk
+import common.WskActorSystem
+import common.WskAdmin
+import common.WskProps
+
+/**
+ * Tests for basic CLI usage. Some of these tests require a deployed backend.
+ */
+@RunWith(classOf[JUnitRunner])
+class WskCliApiGwTests extends BaseApiGwTests with WskActorSystem with JsHelpers with StreamLogging {
+
+ val systemId: String = "whisk.system"
+ override implicit val wskprops = WskProps(authKey = WskAdmin.listKeys(systemId)(0)._1, namespace = systemId)
+ val wsk: common.Wsk = new Wsk
+
+ it should "reject apimgmt actions that are invoked with not enough parameters" in {
+ val invalidArgs = Seq(
+ //getApi
+ ("/whisk.system/apimgmt/getApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq()),
+ //deleteApi
+ (
+ "/whisk.system/apimgmt/deleteApi",
+ ANY_ERROR_EXIT,
+ "Invalid authentication.",
+ Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
+ (
+ "/whisk.system/apimgmt/deleteApi",
+ ANY_ERROR_EXIT,
+ "basepath is required",
+ Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
+ (
+ "/whisk.system/apimgmt/deleteApi",
+ ANY_ERROR_EXIT,
+ "When specifying an operation, the path is required",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "basepath",
+ "/ApiGwRoutemgmtActionTests_bp",
+ "-p",
+ "operation",
+ "get")),
+ //createApi
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "apidoc is required",
+ Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "apidoc is missing the namespace field",
+ Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", "{}")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "apidoc is missing the gatewayBasePath field",
+ Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_"}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "apidoc is missing the gatewayPath field",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp"}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "apidoc is missing the gatewayMethod field",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp"}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "apidoc is missing the action field",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get"}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "action is missing the backendMethod field",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{}}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "action is missing the backendUrl field",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post"}}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "action is missing the namespace field",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL"}}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "action is missing the name field",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_"}}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "action is missing the authkey field",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N"}}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "swagger and gatewayBasePath are mutually exclusive and cannot be specified together",
+ Seq(
+ "-p",
+ "__ow_user",
+ "_",
+ "-p",
+ "accesstoken",
+ "TOKEN",
+ "-p",
+ "apidoc",
+ """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N","authkey":"XXXX"},"swagger":{}}""")),
+ (
+ "/whisk.system/apimgmt/createApi",
+ ANY_ERROR_EXIT,
+ "apidoc field cannot be parsed. Ensure it is valid JSON",
+ Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", "{1:[}}}")))
+
+ invalidArgs foreach {
+ case (action: String, exitcode: Int, errmsg: String, params: Seq[String]) =>
+ val cmd: Seq[String] = Seq(
+ "action",
+ "invoke",
+ action,
+ "-i",
+ "-b",
+ "-r",
+ "--apihost",
+ wskprops.apihost,
+ "--auth",
+ wskprops.authKey) ++ params
+ val rr = wsk.cli(cmd, expectedExitCode = exitcode)
+ rr.stderr should include regex (errmsg)
+ }
+ }
+
+ it should "reject an API created with a non-existent action" in {
+ val testName = "CLI_APIGWTEST15"
+ val testbasepath = "/" + testName + "_bp"
+ val testrelpath = "/path"
+ val testnewrelpath = "/path_new"
+ val testurlop = "get"
+ val testapiname = testName + " API Name"
+ val actionName = testName + "_action"
+ try {
+ val rr = apiCreate(
+ basepath = Some(testbasepath),
+ relpath = Some(testrelpath),
+ operation = Some(testurlop),
+ action = Some(actionName),
+ apiname = Some(testapiname),
+ expectedExitCode = ANY_ERROR_EXIT)
+ rr.stderr should include("does not exist")
+ } finally {
+ apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+ }
+ }
+
+ it should "reject an API created with an action that is not a web action" in {
+ val testName = "CLI_APIGWTEST16"
+ val testbasepath = "/" + testName + "_bp"
+ val testrelpath = "/path"
+ val testnewrelpath = "/path_new"
+ val testurlop = "get"
+ val testapiname = testName + " API Name"
+ val actionName = testName + "_action"
+ try {
+ // Create the action for the API. It must NOT be a "web-action" action for this test
+ val file = TestUtils.getTestActionFilename(s"echo.js")
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT)
+
+ val rr = apiCreate(
+ basepath = Some(testbasepath),
+ relpath = Some(testrelpath),
+ operation = Some(testurlop),
+ action = Some(actionName),
+ apiname = Some(testapiname),
+ expectedExitCode = ANY_ERROR_EXIT)
+ rr.stderr should include("is not a web action")
+ } finally {
+ wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+ apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+ }
+ }
+
+ it should "reject API export when export type is invalid" in {
+ val testName = "CLI_APIGWTEST18"
+ val testbasepath = "/" + testName + "_bp"
+
+ val rr = apiGet(basepathOrApiName = Some(testbasepath), format = Some("BadType"), expectedExitCode = ANY_ERROR_EXIT)
+ rr.stderr should include("Invalid format type")
+ }
+
+ it should "list api alphabetically by Base/Rel/Verb" in {
+ val baseName = "/BaseTestPathApiList"
+ val actionName = "actionName"
+ val file = TestUtils.getTestActionFilename(s"echo-web-http.js")
+ try {
+ // Create Action for apis
+ var action =
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+ println("action creation: " + action.stdout)
+ // Create apis
+ for (i <- 1 to 3) {
+ val base = s"$baseName$i"
+ var api = apiCreate(
+ basepath = Some(base),
+ relpath = Some("/relPath"),
+ operation = Some("GET"),
+ action = Some(actionName))
+ println("api creation: " + api.stdout)
+ }
+ val original = apiList(nameSort = Some(true))
+ val originalFull = apiList(full = Some(true), nameSort = Some(true))
+ val scalaSorted = List(s"${baseName}1" + "/", s"${baseName}2" + "/", s"${baseName}3" + "/")
+
+ val regex = s"${baseName}[1-3]/".r
+ val list = (regex.findAllMatchIn(original.stdout)).toList
+ val listFull = (regex.findAllMatchIn(originalFull.stdout)).toList
+
+ scalaSorted.toString shouldEqual list.toString
+ scalaSorted.toString shouldEqual listFull.toString
+
+ } finally {
+ // Clean up Apis
+ for (i <- 1 to 3) {
+ apiDelete(basepathOrApiName = s"${baseName}$i", expectedExitCode = DONTCARE_EXIT)
+ }
+ wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+ }
+ }
+
+ it should "successfully export an API in YAML format" in {
+ val testName = "CLI_APIGWTEST19"
+ val testbasepath = "/" + testName + "_bp"
+ val testrelpath = "/path"
+ val testnewrelpath = "/path_new"
+ val testurlop = "get"
+ val testapiname = testName + " API Name"
+ val actionName = testName + "_action"
+ val responseType = "http"
+ try {
+ // Create the action for the API. It must be a "web-action" action.
+ val file = TestUtils.getTestActionFilename(s"echo.js")
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+ var rr = apiCreate(
+ basepath = Some(testbasepath),
+ relpath = Some(testrelpath),
+ operation = Some(testurlop),
+ action = Some(actionName),
+ apiname = Some(testapiname),
+ responsetype = Some(responseType))
+ rr.stdout should include("ok: created API")
+
+ rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("yaml"))
+ rr.stdout should include(s"basePath: ${testbasepath}")
+ } finally {
+ wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+ apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+ }
+ }
+
+ it should "successfully export an API when JSON format is explcitly specified" in {
+ val testName = "CLI_APIGWTEST20"
+ val testbasepath = "/" + testName + "_bp"
+ val testrelpath = "/path"
+ val testnewrelpath = "/path_new"
+ val testurlop = "get"
+ val testapiname = testName + " API Name"
+ val actionName = testName + "_action"
+ val responseType = "http"
+ try {
+ // Create the action for the API. It must be a "web-action" action.
+ val file = TestUtils.getTestActionFilename(s"echo.js")
+ wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+ var rr = apiCreate(
+ basepath = Some(testbasepath),
+ relpath = Some(testrelpath),
+ operation = Some(testurlop),
+ action = Some(actionName),
+ apiname = Some(testapiname),
+ responsetype = Some(responseType))
+ rr.stdout should include("ok: created API")
+
+ rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("json"))
+ rr.stdout should include(testbasepath)
+ rr.stdout should include(s"${actionName}")
+ rr.stdout should include regex (""""cors":\s*\{\s*\n\s*"enabled":\s*true""")
+ rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
+ } finally {
+ wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+ apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+ }
+ }
+
+ it should "successfully create an API from a YAML formatted API configuration file" in {
+ val testName = "CLI_APIGWTEST21"
+ val testbasepath = "/bp"
+ val testrelpath = "/rp"
+ val testurlop = "get"
+ val testapiname = testbasepath
+ val actionName = "webhttpecho"
+ val swaggerPath = TestUtils.getTestApiGwFilename(s"local.api.yaml")
+ try {
+ var rr = apiCreate(swagger = Some(swaggerPath))
+ println("api create stdout: " + rr.stdout)
+ println("api create stderror: " + rr.stderr)
+ rr.stdout should include("ok: created API")
+ rr = apiList(basepathOrApiName = Some(testbasepath))
+ rr.stdout should include("ok: APIs")
+ rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+ rr.stdout should include(testbasepath + testrelpath)
+ } finally {
+ apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+ }
+ }
+
+ it should "reject creation of an API from invalid YAML formatted API configuration file" in {
+ val testName = "CLI_APIGWTEST22"
+ val testbasepath = "/" + testName + "_bp"
+ val swaggerPath = TestUtils.getTestApiGwFilename(s"local.api.bad.yaml")
+ try {
+ val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
+ println("api create stdout: " + rr.stdout)
+ println("api create stderror: " + rr.stderr)
+ rr.stderr should include("Unable to parse YAML configuration file")
+ } finally {
+ apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+ }
+ }
+}
--
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].